# 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

- See sidebar options section for more info.

## 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();

- 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
  - 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.
- 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

- In some languages such as PHP, you should make sure you are making changes to the item itself and not a copy of it.
  For example in this assignment: `$mark_me = $menu_list[$current_page]` , when you modify `$mark_me` and for example mark it as active, changes are not reflected in `$menu_list[$current_page]` and therefore, when printing the `$menu_list` list, you won't have modified items.
  For that you should make sure, you are using a reference not a copy: `$mark_me = &$menu_list[$current_page]`
  Now `$mark_me` is a reference to `$menu_list[$current_page]` and therefore