jQuery-ui horizontal menu made easy

This is some code for building a jquery ui horizontal menu. It is based on code by https://codepen.io/seungjaeryanlee/ and modified for icon support and to create a menu automatically from a JSON schema. It’s pretty useful for HTML5 app development.

menu created from JSON
Menu created from JSON schema

HTML

This is how the menu would look be structured if just coded in html

<ul id="menubar">
  <li><div class="icon"><span class="ui-icon ui-icon-folder-open"></span><a href="#">Alpha</a></div>
     <ul>
      <li><div><a href="#">Beta 1</a></div></li>
      <li>
        <div class="icon"><span class="ui-icon ui-icon-folder-open"></span><a href="#">Beta 2</a></div>
        <ul>
          <li><div class="icon"><span class="ui-icon ui-icon-folder-open"></span><a href="#">Beta 2a</a></div></li>
          <li><div><a href="#">Beta 2b</a></div></li>
        </ul>
      </li>
      <li><div><a href="#">Beta 3</a></div></li>
    </ul>
  </li>
  <li>
    <div><a href="#">Beta</a></div>
    <ul>
      <li><div><a href="#">Beta 1</a></div></li>
      <li>
        <div><a href="#">Beta 2</a></div>
        <ul>
          <li><div><a href="#">Beta 2a</a></div></li>
          <li><div><a href="#">Beta 2b</a></div></li>
        </ul>
      </li>
      <li><div><a href="#">Beta 3</a></div></li>
    </ul>
  </li>
  <li><div><a href="#">Gamma</a></div></li>
  <li><div><a href="#">Delta</a></div></li>
 </ul>

javascript

menuStructure is the JSON menu descriptor, the code setUpMenuHTML and addMenuHTML create HTML from this schema in the format of the html above.

var menuStructure = {menu: [
                        { name: "file",  
                          menu: [
                              {name: "Open", icon: "ui-icon ui-icon-folder-open"}, 
                              {name: "save", icon: "ui-icon ui-icon-disk"}
                          ]
                         },
                        {name: "ImageProcessing", icon: "ui-icon ui-icon-image",
                         menu: [
                             {name: "Invert"}, 
                             {name: "threshold"}, 
                             {name: "binary", 
                              menu: [
                                    {name: "erode"}, 
                                    {name: "open"}, 
                                    {name: "close"}
                                    ]
                             }
                            ]
                        },
                        {name: "help", icon: "ui-icon ui-icon-help"}
                    ]};
    

function addMenuHTML(ME, $selector)
{
    var $ulOuter = $selector;
    
    if(!$selector.is('#menubar'))
        $ulOuter = $("
    ").appendTo($selector); for(var j=0;j").appendTo($ulOuter); if(ME.menu[j].icon) { str = '
    '+ME.menu[j].name+'
    '; } else{ str = '
    ' + ME.menu[j].name + '
    '; } $(str).appendTo($liInner); // call recursively on nested menu elements if(ME.menu[j].menu) addMenuHTML(ME.menu[j], $liInner); } } function setUpMenuHTML() { var $menu = $('#menubar'); $menu.empty(); addMenuHTML(menuStructure, $menu); } function setUpMenu() { $('#menubar').menu(); $('#menubar').menu({ position: { my: 'left top', at: 'left bottom' }, blur: function() { $(this).menu('option', 'position', { my: 'left top', at: 'left bottom' }); }, focus: function(e, ui) { if ($('#menubar').get(0) !== $(ui).get(0).item.parent().get(0)) { $(this).menu('option', 'position', { my: 'left top', at: 'right top' }); } }, }); } $(document).ready(function() { setUpMenuHTML(); setUpMenu(); });

    css

    the CSS ensures that the menuu is horizonal and that the icons are correctly displayed next to the menu names and that the sub menus also indent correctly

    #menubar {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
    }
    
    ul > li a{
      max-width:100%;
      color: inherit; /* blue colors for links too */
      text-decoration: inherit; /* no underline */
    }
    
    li > div {
      white-space: nowrap;
      overflow: hidden;
    }
    
    /* Make jQuery UI Menu into a horizontal menubar with vertical dropdown */
    #menubar > li { /* Menubar buttons */
      #text-align: center;
      display: inline-block;
    }
    
    #menubar li > div:not(.icon) {
      padding-left: 0.3em !important;
    }
    
    #menubar li > div.icon {
      padding-left: 1.5em;
    }
    
    #menubar > li > ul > li { /* Menubar buttons inside dropdown */
      display: block;
    }
    
    /* Change dropdown carets to correct direction */
    #menubar > li > div > span.ui-icon-caret-1-e {
      /* Caret on menubar */
      background:url(https://www.drupal.org/files/issues/ui-icons-222222-256x240.png) no-repeat -64px -16px !important;
    }
    #menubar ul li div span.ui-icon-caret-1-e {
      /* Caret on dropdowns */
      background:url(https://www.drupal.org/files/issues/ui-icons-222222-256x240.png) no-repeat -32px -16px !important;
    }