Sidebar

Sidebar Basics

1. Layout

  • Default HTML layout used for sidebar is:
    1. shortcut buttons: optional
    2. .nav-list: contains sidebar items
    3. expand/collapse button: optional
    
    
    Please note that for most Javascript functions to perform without problem, you should specify id attribute of elements, for example, sidebar element can have #sidebar id attribute.
  • Starting with the following file you can find more details:
    mustache/app/views/layouts/partials/_shared/sidebar.mustache

2. Menu item

  • First level menu item has the following markup:
  • Item text
  • mustache/app/views/layouts/partials/_shared/sidebar/item.mustache
  • Icons should have .menu-icon class.
    First level menu item's text should be inside .menu-text element, but this isn't needed for deeper levels:
    
    
  • level 2 item text
  • level 2 item text

3. Shortcut Buttons

  • It consists of .sidebar-shortcuts-large and .sidebar-shortcuts-mini which is displayed when sidebar is minimized (collapsed)
  • 
    

4. Minimize Button

  • Sidebar collapse/expand button is used to minimize/restore sidebar.
    It should have a data-target attribute which points to sidebar ID.
      
    
  • There is also another .sidebar-expand button for sidebar in 2nd mobile view style.
    In that case, sidebar is automatically minimized and the button is used to expand it.
    Also it should have a data-target attribute which points to sidebar ID.
     
    
  • You can use data-icon1 and data-icon2 attributes to specify icons to use in collapsed/expanded state

5. Other notes

  • To add a badge or label inside menu items, you should put it inside .menu-text element:
     
       Menu Text
       4
     
    
    You can also include a tooltip:
     
       Menu Text
       
         
       
     
    

6. Sidebar options

Sidebar functions

Basic functions

  • To enable sidebar functions on an element you should use the following piece of code:
     $('.sidebar').ace_sidebar();
     //or
     $('#my-specific-sidebar').ace_sidebar();
    
  • The following options are available when initiating ace_sidebar function:
    • duration: submenu toggle duration.
    • hide_open_subs: whether to hide open submenus when opening a new one.
  • By default all .sidebar elements are initiliazed on page load.
  • The following functions are available for sidebar:
    • toggleMenu: collapses or expands sidebar.
       $('.sidebar').ace_sidebar('toggleMenu');
       $('.sidebar').ace_sidebar('toggleMenu', toggleButton);
       //if there is an optional toggleButton element, its icons will be flipped
      
       $('.sidebar').ace_sidebar('toggleMenu', false);
       //optional false value means don't save changes to cookies
      
       $('.sidebar').ace_sidebar('toggleMenu', [toggleButton , false/true ]);
       //optional second value means save or don't save changes to cookies
      
    • collapse collapses sidebar and expand expands sidebar:
       $('#my-sidebar').ace_sidebar('collapse');
       $('#my-sidebar').ace_sidebar('collapse', toggleButton);
       //if there is an optional toggleButton element, its icons will be flipped
      
      Please note that if you want to have minimized sidebar by default you should make the changes using CSS classes as described in sidebar settings
    • mobileToggle toggles sidebar in mobile view.
       $('#sidebar').ace_sidebar('mobileToggle');
       $('#sidebar').ace_sidebar('mobileShow');
       $('#sidebar').ace_sidebar('mobileHide');
      
    • toggle, hide or show are used for submenus:
       $('#my-sidebar').ace_sidebar('toggle', [sub, 300]);
       //first parameter is submenu to toggle and second is duration in milliseconds.
      

Sidebar scrollbars

  • There are two approaches for sidebar scrollbars which you can choose by using custom JS builder tool.
  • First approach is used by default and works only for fixed sidebar.
    There is no cropping of elements because of overflow:hidden CSS property.
  • Second approach can be used both by fixed and normal sidebars and uses overflow:hidden CSS property.
    Native browser scrollbars are used touch devices.
  • To add scrollbars to sidebar you should use the following function:
     $('.sidebar').ace_sidebar_scroll({
        //options here
     });
    
    By default all .sidebar elements have scrollbars enabled on page load and activated when appropriate.
  • Note that you can also specify the following options using data-* attributes.
    
    
    The following options are available for first approach:
    • scroll_to_active scroll to active item on page load
    • include_shortcuts include shortcut buttons in scroll area
    • include_toggle include toggle button in scroll area or not
    • scroll_style scrollbar style as described in custom scrollbars section
    • mousewheel_lock whether to lock mouse wheel on sidebar even if it hasn't scrollbars or not
    • only_if_fixed used in 2nd approach only
    • smooth_scroll used in first approach only. Specify a number to enable smooth scrolling or false to disable
  • The following functions are also available:
    • reset reset scrollbars
    • updateStyle updates scrollbars style class:
       $('#my-sidebar').ace_sidebar_scroll('updateStyle', 'scroll-dark no-track');
       //for example such update is done which switching to another skin in Ace's demo
      

Submenu positioning and scrollbars

  • To enable submenu adjustment, hiding delay and scrollbar feature you should use the following function:
     $('.sidebar').ace_sidebar_hover({
        //options here
     });
    
    By default all .sidebar elements have this feature enabled on page load and activated when appropriate.
  • The following options are available:
    • sub_hover_delay time in milliseconds to hide a submenu after mouse leaves it. Default is 750
    • sub_scroll_style scrollbar style as described in custom scrollbars section
  • The following functions are also available:
    • reset reset scrollbars
    • updateStyle updates submenu scrollbars style class:
       $('#my-sidebar').ace_sidebar_hover('updateStyle', 'scroll-dark no-track');
       //for example it can be done when switching to another skin dynamically
      
    • changeDir changes scrollbars direction (left) for example if you are using RTL:
       $('#my-sidebar').ace_sidebar_hover('changeDir', 'left');
      

Responsive Sidebar

Mobiles Views

  • There are 3 styles of responsive (mobile view) sidebar when screen size is below 992px.
    You can change this value by changing Bootstrap @grid-float-breakpoint-max variable and recompiling LESS files.
    See CSS section

1. Default mobile menu style

  • Default mobile menu style

    You should add .responsive class to .sidebar element.
  • You can also add .push_away class to .sidebar to push content when sidebar is shown:
     
    
  • You can add data-auto-hide=true attribute for sidebar to automatically hide when user clicks outside of its area:
     
    

2. Automatically minimized menu style

  • You should add .responsive-min class to .sidebar element and there should also be an invisible toggle button present, right before sidebar.
    An additional .sidebar-toggle.sidebar-expand button, expands sidebar in mobile view: (More info)
    It should have a data-target attribute which points to sidebar ID.
    
    
    
  • You can add data-auto-hide=true attribute for sidebar to automatically become minimized when user clicks outside of its area:
     
    

3. Bootstrap collapse style

  • For this you should add .collapse.navbar-collapse class to .sidebar element and have the correct toggle buttons inside navbar:
    
    

Toggle Button

  • In default responsive (mobile) style and collapsible responsive style, toggle buttons are used to show and hide sidebar.
  • Buttons can are either before brand text container (.navbar-header) or inside it and it should have data-target attribute which points to sidebar's ID.
     
    
     
    
  • If you want to use old style toggle button, you should insert it before .sidebar element.
     
       Toggle sidebar
       
     
     
    

    It should have a span.toggler-text inside it and you can change MENU text to something else by modifying @toggler-text variable inside assets/css/less/sidebar/old-toggle-button.less and recompiling ace.less
  • In 2nd mobile menu style, you should add an invisible .menu-toggler element right before .sidebar
     
     
    
  • For collapse style sidebar in mobile view (3rd style), you should use data-toggle and data-target attributes:
    <button class="pull-right navbar-toggle collapsed" type="button"
               data-toggle="collapse" data-target=".sidebar">
      <span class="sr-only">Toggle sidebar</span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </button>
    
     
     
    

Sidebar Options

1. Horizontal Sidebar

  • For horizontal menu you should add .h-sidebar class to .sidebar and .h-navbar to .navbar element:
     
     
  • You should also add .hover class to all LI elements, so that submenus are shown on mouse hover:
     
    
  • Add .no-gap to horizontal menu to remove gap.
    Add .lower-highlight to move the highlight bar lower.
    Add .h-navbar to .navbar to add shadow to it.
    
    
    
    
  • Horizontal menu is only visible when screen width is above 991px.
    You can choose any of the three possible mobile menu styles for smaller widths.
  • Also, in demo page, when horizontal menu is fixed and you scroll down, it moves up gradually.
    To enable this, you should include the following code in your page:
    mustache/app/views/assets/scripts/top-menu.js
  • If you want the header (h1) text to be aligned with content area text, you can either add .no-margin-left class to h1 header element or add .no-margin class to the .row element which encloses content area!

2. Submenu on Hover

  • You can have submenus to be displayed on mouse hover instead of click.
  • For that you should add .hover class to each LI element and also add .arrow element before submenus.
     
    
  • Hover submenus are only available when screen width is above 991px.
    You can change that by modifying @screen-hover-menu variable inside assets/css/less/variables.less and recompile ace.less or use CSS builder tool.

3. Compact Sidebar

  • Simply add .compact class to .sidebar element:
     
    
  • Compact sidebar is only available when screen width is above 991px.
    You can change that by modifying @@screen-compact-menu variable inside assets/css/less/variables.less and recompile ace.less or use CSS builder tool.

4. Highlight Item

  • An alternative active item highlight.
    Add .highlight to LI elements:
     
    

5. Fixed Sidebar

  • Adding .sidebar-fixed class to .sidebar element makes it fixed by default:
     
    
  • For more info please see sidebar settings

6. Minimized Sidebar

  • Adding .menu-min class to .sidebar element makes it minimized by default:
     
    
  • For more info please see sidebar settings

7. Multiple Sidebar

  • You can have more than one sidebar on a page.
  • Each one should have .sidebar class and an ID attribute.
  • First sidebar should be at its default place and second should be inside .main-content-inner:
  • If second sidebar is not horizontal, then .page-content should also have .main-content class and .footer should be moved after it:

Sidebar Active Item

Ajax

  • If your page content is updated via ajax and you want to mark a different menu item as active, you can do like this as an example:
    //inside the function when ajax content is loaded
    
    //somehow get a reference to our newly clicked(selected) element's parent "LI"
    var new_active = $(this).parent();
    
    //remove ".active" class from all (previously) ".active" elements
    $('.nav-list li.active').removeClass('active');
    
    //add ".active" class to our newly selected item and all its parent "LI" elements
    new_active.addClass('active').parents('.nav-list li').addClass('active');
    
    //you can also update breadcrumbs:
    var breadcrumb_items = [];
    //$(this) is a reference to our clicked/selected element
    $(this).parents('.nav-list li').each(function() {
      var link = $(this).find('> a');
      var text = link.text();
      var href = link.attr('href');
      breadcrumb_items.push({'text': text, 'href': href});
    })
    //now we have a breadcrumbs list and can replace breadcrumbs area
    
  • If you are using a client side application framework such as ember.js or angular.js, you may have other approaches that work better in the specific context.

non-Ajax

  • If you navigate to other pages without ajax, you can have several approaches depending on your application.
  • For example if you have a list of pages retrieved from a data source, you can lookup the item that matches current page and mark it as active.
    You should also mark its parents as active and open
  • In the following example we have a list of items.
    We find our current item using its identifier.
    Then we mark it as active, find its parent, mark the parent as active & open and repeat this action.
  • Sample PHP code:
    //suppose we have a list of pages (associative array or other data structure)
    //$menu_list = ... //retrieved from database
    //or
     $menu_list = array(
        'id or name of page 1' => array (
             'href' => '#link1',
             'text' => 'item name or text',
           'parent' => 'parent id or name'
        )
        ,
       'id or name of page 2' => array (
             'href' => '#link2',
             'text' => 'item name or text',
           'parent' => 'parent id or name'
        )
        ,
       'new-user' => array (
             'href' => 'user/create',
             'text' => 'Add User',
           'parent' => 'operations'
        )
        ...
     );
    
    //we somehow know the ID or tag or hash of the current page
    //perhapse from a database lookup or by simply checking its URL
    //for some pointers such as ID, file name, category name, etc ...
    $current_page = 'new-user';
    $breadcrumbs = array();//let's create our breadcrumbs array as well
    
    //make_me should be a reference to current_item not a copy of it
    $mark_me = &$menu_list[$current_page];
    $open = false;
    while(true) {//you can also use a recursive function instead of a loop
      $mark_me['active'] = true;//mark this as "active"
      if( $open ) $mark_me['open'] = true;//mark this as "open"
      
      $breadcrumbs[] = $mark_me;
    
      $parent_id = $mark_me['parent'];//see if it has a parent
      if( $parent_id == null || !isset($menu_list[$parent_id]) ) break;//if not, break
      
      $mark_me = &$menu_list[$parent_id];//set item's parent as the new "mark_me" and repeat
      $open = true;//parent elements should be marked as "open" too
    }
    
    foreach($menu_list as $id => $menu_item) {
      print('<li class="');
       if( $menu_item['active'] ) print('active');
       if( $menu_item['open'] ) print(' open');
      print('">');
      //something like <li class="active open"> will be printed
      //...
      //print other parts of menu item
    }
    
    //now we also have a list of breadcrumb items to print later
    

    Sample Javascript code (for example in Nodejs):
    //suppose we have a list of pages (associative array or other data structure)
    //var menu_list = ... //retrieved from database
    //or
     var menu_list = {
        'id or name of page 1' : {
             'href' : '#link1',
             'text' : 'item name or text',
           'parent' : 'parent id or name'
        }
        ,
       'id or name of page 2' : {
             'href' : '#link2',
             'text' : 'item name or text',
           'parent' : 'parent id or name'
        }
        ,
       'new-user' : {
             'href' : 'user/create',
             'text' : 'Add User',
           'parent' : 'operations'
        }
        ...
     };
    
    //we somehow know the ID or tag or hash of the current page
    //perhapse from a database lookup or by simply checking its URL
    //for some pointers such as ID, file name, category name, etc ...
    var current_page = 'new-user';
    var breadcrumbs = [];//let's create our breadcrumbs array as well
    
    //make_me should be a reference to current_item not a copy of it
    var mark_me = menu_list[current_page];
    var open = false;
    while(true) {//you can also use a recursive function instead of a loop
      mark_me['active'] = true;//mark this as "active"
      if( open ) mark_me['open'] = true;//mark this as "open"
      
      breadcrumbs.push(mark_me);
    
      var parent_id = mark_me['parent'];//see if it has a parent
      if( parent_id == null || !(parent_id in menu_list) ) break;//if not, break
      
      mark_me = menu_list[parent_id];//set item's parent as the new "mark_me" and repeat
      open = true;//parent elements should be marked as "open" too
    }
    
    var output = '';
    for(var id in menu_list) if(menu_list.hasOwnProperty(id)) {
      var menu_item = menu_list[id];
      output += '<li class="';
       if( menu_item['active'] ) output += 'active';
       if( menu_item['open'] ) output += ' open';
      output += '">';
      //something like <li class="active open"> will be printed
      //...
      //print other parts of menu item
    }
    console.log(output);
    
    //now we also have a list of breadcrumb items to print later