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 &#8595;</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 &#8595;</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 &#8595;", 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 &#8595;", 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.

kick it on DotNetKicks.com

Attachments