Ejectamenta News Summary

JSON schema jQuery-ui horizontal menu

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.

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 = $("<ul></ul>").appendTo($selector);
            
    for(var j=0;j<ME.menu.length;j++)
    {
        var $liInner = $("<li></li>").appendTo($ulOuter);

        if(ME.menu[j].icon)
        {
            str = '<div class="icon"><span class="' + ME.menu[j].icon + '"></span>'+ME.menu[j].name+'</div>'; 	
        }
        else{
             str = '<div>' + ME.menu[j].name + '</div>'; 	
        }
        
         $(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;
}

Return
Oct 4, 2018 Category: Ejectamenta News Posted by: dave