Sep
26
2007
Suckerfish menu with ASP.NET and JQuery
Posted by admin under
Ajax
This time I am giving you the ASP.NET code for creating a Suckerfish menu in ASP.NET. I really like the multiple level/hover shows next level type of menus like in these screenshots:
I keep trying to push for JQuery - not only is it small, wellwritten, MIT licensed (allows for use and distribution in commercial projecvts as well) but it's also a very competent Javascript library. The readymade JQuery plugin we are gonna use is Superfish.
Now what I *really* would like to emphasize in this post is the fact that when looking at the code I understand if you feel like - oh what a quick and dirty job. And I admit it. I could have gone the whole way and create a fullblown asp.net server side control, adding viewstate for handling state etc - however my point is that it doesn't have to be all that all the time I mean lets look at the needed javascript/pure html to get this menu rolling:
<script type="text/javascript" src="../jquery-1.2.1.js"></script>
<script type="text/javascript" src="../helperPlugins.js"></script>
<script type="text/javascript" src="../superfish.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(".nav")
.superfish({
pathClass : 'current',
animation : {opacity:'show'},
delay : 1000
});
});
</script>
...
...
...
<ul class="nav">
<li>
<a href="#">menu item ↓</a>
<ul>
<li><a href="#">subitem 1a</a></li>
<li><a href="#">subitem 1b</a></li>
<li><a href="#">subitem 1c</a></li>
<li><a href="#">subitem 1d</a></li>
<li><a href="#">subitem 1e</a></li>
</ul>
</li>
<li class="current">
<a href="#">menu item ↓</a>
<ul>
<li><a href="#">subitem 2a</a></li>
<li class="current"><a href="#">* current *</a></li>
<li><a href="#">subitem 2c</a></li>
<li><a href="#">subitem 2d</a></li>
<li><a href="#">subitem 2e</a></li>
</ul>
</li>
It's not much and to be honest - I can't really see the type of application where you change current menu item on a postback? So what I present here is a solution proven good enough for me in my projects - and if it's not good enough for you then at least you might have some base to create your own control from.
Lets look at some C# code now. We know we are supposed to create a markup (pure ul/li - I like that too) looking like above. So I have a generic MenuHelper class
public class MenuHelperRoot
{
public virtual bool IsCurrent(MenuItem oItem)
{
if (System.Web.HttpContext.Current.Request.Url.ToString().ToLower().IndexOf(oItem.Link.ToLower())>= 0)
return true;
return false;
}
public string ULDecoration = "class=\"nav\"";
public string LICurrentDecoration = "class=\"current\"";
public System.Collections.Generic.List<MenuItem> Items = new System.Collections.Generic.List<MenuItem>();
public string GetHtml()
{
System.Text.StringBuilder oBuilder = new System.Text.StringBuilder();
oBuilder.Append("<ul ");
oBuilder.Append(ULDecoration);
oBuilder.Append(">");
foreach (MenuItem oItem in Items)
oBuilder.Append(oItem.GetHtml());
oBuilder.Append("</ul");
return oBuilder.ToString();
}
}
public class MenuItem
{
public MenuItem(string sLink, string sText, MenuHelperRoot oRoot)
{
Link = sLink;
Text = sText;
m_Root = oRoot;
}
private MenuHelperRoot m_Root;
public string Link = "";
public string Text = "";
public System.Collections.Generic.List<MenuItem> Items = new System.Collections.Generic.List<MenuItem>();
public bool RecursiveIsCurrent
{
get
{
if (Link != "#" && m_Root.IsCurrent(this))
return true;
foreach (MenuItem oItem in Items)
if (oItem.RecursiveIsCurrent)
return true;
return false;
}
}
public string GetHtml()
{
System.Text.StringBuilder oBuilder = new System.Text.StringBuilder();
oBuilder.Append("<li " + (RecursiveIsCurrent ? " " + m_Root.LICurrentDecoration : "") + ">");
oBuilder.Append("<a href=\"" + Link + "\">" + Text + "</a>");
if (Items.Count > 0)
{
oBuilder.Append("<ul>");
foreach (MenuItem oItem in Items)
oBuilder.Append(oItem.GetHtml());
oBuilder.Append("</ul>");
}
oBuilder.Append("</li>");
return oBuilder.ToString();
}
}
Now the idea is that you create your own application specific class deriving from that:
public class SuckerDemoMenuHelper : MenuHelperRoot
{
public SuckerDemoMenuHelper()
{
//Setup menu...
MenuItem oItemFoo = new MenuItem("#", "Foo functions ↓", this);
Items.Add(oItemFoo);
oItemFoo.Items.Add(new MenuItem("foofunctions.aspx?id=1", "Foo no 1", this));
oItemFoo.Items.Add(new MenuItem("foofunctions.aspx?id=2", "Foo no 2", this));
oItemFoo.Items.Add(new MenuItem("foofunctions.aspx?id=3", "Foo no 3", this));
oItemFoo.Items.Add(new MenuItem("foofunctions.aspx?id=4", "Foo no 4", this));
MenuItem oItemBar = new MenuItem("#", "Bar functions ↓", this);
Items.Add(oItemBar);
oItemBar.Items.Add(new MenuItem("barfunctions.aspx?id=1", "Bar no 1", this));
oItemBar.Items.Add(new MenuItem("barfunctions.aspx?id=2", "Bar no 2", this));
oItemBar.Items.Add(new MenuItem("barfunctions.aspx?id=3", "Bar no 3", this));
oItemBar.Items.Add(new MenuItem("barfunctions.aspx?id=4", "Bar no 4", this));
}
}
and in your aspx/master file you feed the GetHtml() retult into a literal:
SuckerDemoMenuHelper oHelper = new SuckerDemoMenuHelper();
litSucker.Text = oHelper.GetHtml();
The downloadable zip file contains all the code you need, C#, VS 2005 is used. You can also view the suckerfish asp.net sourcecode online here.
Attachments