Bootstrap Navbar

From ProcessWire
Jump to: navigation, search

Imbox notice.png This Article requires peer review

This article is complete, but may benefit from checking for accuracy and grammar, testing any code or adding further information that will make it clearer.


Contents

The Twitter Bootstrap Navbar needs particular classes to be able to operate fully, just as with other frameworks. This code shown below is for displaying the standard ProcessWire navigation system for Bootstrap.

Requirements

Since this is for use with Twitter Bootstrap, then you need to have the framework installed.

There are four script requirements:

jquery.js (the most recent version should be used for the most recent version of Bootstrap) bootstrap.min.js bootastrap.min.css bootstrap-responsive.min.css (optional, but recommended)

Plus any overrides you may want to use.

References

It is worth reading up on how the code works on the Bootstrap site.

Navbar Documentation

The more recent versions of Bootstrap now allow a sub navigation level and the code below takes advantage of the improvement.

The Code

I have split the code into two parts:

  • Basic code for the header of the site
  • An include to handle the menu

The reason for doing this is makes it much easier to change the navbar position and styling and then to simply include the menu itself.

The Navbar

This Navbar is fixed at the top of the site. It includes the "brand" which would normally be a site title and will collapse to a drop down for Tablets and Phones.

  1.  <!-- NAVBAR -->
  2.     <div class="navbar navbar-fixed-top">
  3.       <div class="navbar-inner">
  4.         <div class="container">
  5.           <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
  6.             <span class="icon-bar"></span>
  7.             <span class="icon-bar"></span>
  8.             <span class="icon-bar"></span>
  9.           </a>
  10.           <a class="brand" href="#">YOUR SITE TITLE></a>
  11.           <div class="nav-collapse collapse">
  12. 		<?php
  13. 			include("./TB_topnav.inc"); 
  14. 		?>
  15.           </div><!--/.nav-collapse -->
  16.         </div>
  17.       </div>
  18.     </div><!-- /navbar -->

Note that this includes a file TB_topnav.inc on line 13

This is the file that contains the actual menu.

The Menu

The menu needs to retrieve the children of the Home page as well as the children of the children for Sub Menus which are supported from Bootstrap 2.2.1 onwards.

This new version (Feb 2013) allows for endless sub-categories. However, this might not be a sensible to use for touch devices and would be better to use just one level of dropdown items. No alteration of this script is necessary, simply restrict the menu in the Pages section of the admin.

Note: The Top level item where they have children cannot be linked to a page. This is to allow "click to open" for touch devices. So you need to arrange your pages accordingly.

Bootstrap 3 - there is no guarantees that this will work in Bootstrap 3 (whenever that comes out) simply because they are considering scrapping sub menus.

This code would be the content of TB_topnav.inc.

  1. <?php
  2.  
  3. /*
  4.  
  5. Navigation for ProcessWire using the Bootstrap 2.2.2 markup
  6.  
  7. This menu was written by Soma based on work by NetCarver and a bit thrown in by Joss
  8.  
  9. */
  10.  
  11. function renderChildrenOf($pa, $output = '', $level = 0) {
  12.     $output = '';
  13.     $level++;
  14.     foreach($pa as $child) {
  15.         $atoggle = '';
  16.         $class = '';
  17.         if ($child->numChildren && count($child->parents) == 1) {
  18.             $class .= 'dropdown';
  19.             $atoggle .= ' class="dropdown-toggle" data-toggle="dropdown"';
  20.         } else if($child->numChildren && $child->id != 1){
  21.             $class .= 'dropdown-submenu';
  22.         }
  23.         // Makes the current page and it's top level parent add an active class
  24.         $class .= ($child === wire("page") || $child === wire("page")->rootParent) ? " active" : '';
  25.         $class = strlen($class) ? " class='".trim($class)."'" : '';
  26.         $output .= "<li$class><a href='$child->url'$atoggle>$child->title</a>";
  27.  
  28.         // If this child is itself a parent and not the root page, then render it's children in their own menu too...
  29.         if($child->numChildren && $child->id != 1) {
  30.             $output .= renderChildrenOf($child->children, $output, $level);
  31.         }
  32.         $output .= '</li>';
  33.     }
  34.     $outerclass = ($level == 1) ? "nav nav-pills" : 'dropdown-menu';
  35.     return "<ul class='$outerclass'>$output</ul>";
  36. }
  37.  
  38. // bundle up the first level pages and prepend the root home page
  39. $homepage = $pages->get(1);
  40. $pa = $homepage->children;
  41. $pa = $pa->prepend($homepage);
  42.  
  43. // Set the ball rolling...
  44. echo renderChildrenOf($pa);

Limitations

The Bootstrap menu has one particular limitation in that any "parent" item in the menu cannot link to content.

So, if you have an About section of your webiste with one parent page (About) and a couple of children, on the menu, only the children will be linked - the About page will be simply a place holder.

So, when designing your website and your page structure, bear this in mind and make sure your parents are just pages linked to blank templates with only a title field, since they will not need any other content, unless you include (for example) a breadcrumb trail on the child pages which links to the parent page, in which case something like the following code will display a list of child pages if there are any.

  1. <?php
  2. 	if($page->numChildren > 0){
  3. 		echo "<h4>Select a Subpage</h4>";
  4. 		echo "<ul>";
  5. 		foreach($page->children as $child){
  6. 			echo "<li><a href={$child->url}>{$child->title}</a></li>";
  7. 		}
  8. 		echo "</ul>";
  9. 	} else {
  10. 		echo $page->body;
  11. 	}
  12. ?>
Personal tools
Namespaces

Variants
Actions
Navigation
Processwire
Toolbox