Has anyone written HTMLHelper classes for MVC that help with Yahoo's UI Library
For example, I wrote a helper method for converting a βmenu modelβ to the HTML markup needed to support Yahoo Management . The MVC pattern works well, because obviously, if I decide to switch to another implementation of the menu, I can just write a new helper and not touch the model.
This code works for me, but not fully tested, and you can use it.
First, we need a simple data structure for the menu model itself. You would add this to your page model with the usual MVC conventions. For example, I am viewing a list of menu items from my view through ViewData.Model.MainMenu.MenuOptions .
public class MenuItem { public string Text { get; set; } public string Description { get; set; } public string RouteURL { get; set; } public bool SeparatorBefore { get; set; } public List<MenuItem> MenuItems { get; set; } }
Extension method. Put in the namespace available to your view.
public static class YUIExtensions { public static string RenderMenu(this HtmlHelper html, string id, List<MenuItem> menuItems) { // <div id="mnuTopNav" class="yuimenubar yuimenubarnav"> // <div class="bd"> // <ul class="first-of-type"> // <li class="yuimenubaritem first-of-type"><a class="yuimenubaritemlabel" href="#store">Store</a></li> // <li class="yuimenubaritem"><a class="yuimenubaritemlabel" href="#products">Products</a> // <div id="communication" class="yuimenu"> // <div class="bd"> // <ul> // <li class="yuimenuitem"><a class="yuimenuitemlabel" href="http://360.yahoo.com">360°</a></li> // <li class="yuimenuitem"><a class="yuimenuitemlabel" href="http://mobile.yahoo.com">Mobile</a></li> // <li class="yuimenuitem"><a class="yuimenuitemlabel" href="http://www.flickr.com">Flickr Photo Sharing</a></li> // </ul> // </div> // </div> // </li> // </ul> // </div> //</div> int menuId = 0; HtmlGenericControl menuControl = CreateControl(html, id, 0, ref menuId, menuItems); // render to string StringWriter sw = new StringWriter(); HtmlTextWriter tw = new HtmlTextWriter(sw); tw.Indent = 1; menuControl.RenderControl(tw); return sw.ToString(); } private static HtmlGenericControl CreateControl(HtmlHelper html, string id, int level, ref int menuId, List<MenuItem> currentItems) { var menu = new HtmlGenericControl("div"); menu.Attributes["class"] = (level == 0) ? "yuimenubar yuimenubarnav" : "yuimenu"; menu.Attributes["id"] = id; var div_bd = new HtmlGenericControl("div"); menu.Controls.Add(div_bd); div_bd.Attributes["class"] = "bd"; HtmlGenericControl ul = null; int i = 0; foreach (var menuItem in currentItems) { if (ul == null || menuItem.SeparatorBefore) { ul = new HtmlGenericControl("ul"); div_bd.Controls.Add(ul); if (i == 0) { ul.Attributes["class"] = "first-of-type"; } } var menuItem_li = new HtmlGenericControl("li"); menuItem_li.Attributes["class"] = (level == 0) ? "yuimenubaritem" : "yuimenuitem"; if (i == 0) { menuItem_li.Attributes["class"] += " first-of-type"; } ul.Controls.Add(menuItem_li); var href = new HtmlGenericControl("a"); href.Attributes["class"] = (level == 0) ? "yuimenubaritemlabel" : "yuimenuitemlabel"; href.Attributes["href"] = menuItem.RouteURL; href.InnerHtml = menuItem.Text; menuItem_li.Controls.Add(href); if (menuItem.MenuItems != null && menuItem.MenuItems.Count > 0) { menuItem_li.Controls.Add(CreateControl(html, id + "_" + (menuId++), level + 1, ref menuId, menuItem.MenuItems)); } i++; } return menu; } }
Stick to this code where you want to generate the menu in your view (I have this on the main page):
<%= Html.RenderMenu("mnuTopNav", ViewData.Model.MainMenu.MenuOptions) %>
If you are lazy or do not know about YUI, you will also need this in <HEAD>
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?2.6.0/build/menu/assets/skins/sam/menu.css"> <script type="text/javascript" src="http://yui.yahooapis.com/combo?2.6.0/build/yahoo-dom-event/yahoo-dom-event.js&2.6.0/build/container/container_core-min.js&2.6.0/build/menu/menu-min.js"></script>
Markup is currently being created for the top navigation bar of the navigation style - but it can be easily changed.
I was hoping someone else would do the same for some other controls.
It seems like a good candidate for an open source project, but I don't have time to start this.
Implementation recommendations are welcome!