Showing posts with label Zend_Navigation. Show all posts
Showing posts with label Zend_Navigation. Show all posts

Tuesday, June 15, 2010

Layout and Navigation, Part 3

Part 1 of this series showed how to modify the ZF quickstart application to use Zend_Layout for creating a site-wide template. Part 2 added Zend_Navigation for creating a left side menu and breadcrumbs. In this part, we'll have some fun by changing the default menu layout to use a jQuery plugin by Joel Birch called superfish (an enhanced version of suckerfish), a super sexy top navigation menu with dropdowns. Start by folling the preceeding link to the source and downloading the files, then copy the css, images, and js folders into your /public directory. We'll scrap the old style sheet and use the superfish style sheet instead, as well as including and calling the superfish scripts. We will need a very short custom stylesheet as well, which will be in styles.css. Let's go ahead and use the headScript and headLink view helpers as well. The HEAD of layout.phtml should look like this:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My Site</title>
<?php
// superfish styles
$this->headLink()
//->appendStylesheet('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/themes/base/jquery-ui.css')
->appendStylesheet('/css/superfish.css')
->appendStylesheet('/css/styles.css');

// jQuery and superfish scripts (hoverIntent is optional)
$this->headScript()
->appendFile('http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js')
->appendFile('/js/superfish.js')
->appendFile('/js/hoverIntent.js')
->appendScript("$(document).ready(function() { $('ul.sf-menu').superfish(); }");

echo $this->headLink();
echo $this->headScript();
?>
</head>
Superfish is actually very easy to hook up into Zend_Menu because everything keys off the top-level ul class. It turns out that there is a method for setting this, aptly named setUlClass(). So here is the BODY of layout.phtml:
<body>
<?php
// menu helper, use sf-menu as class for top-level ul element
echo $this->navigation()->menu()->setUlClass('sf-menu');
?>

<div class="content">
<?php
// fetch 'content' key using layout helper:
echo $this->layout()->content;
?>
</div>
</body>
Remember how I said we'll need another short stylesheet? That's because otherwise the page content appears to the right of the menu. No problem, just add the following lines to /public/css/styles.css:
div.content {
clear: left;
}
Super easy, no? And this gets us most of the way there. However, if you want those nifty little arrow indicators (and I'm sure you do) we'll have to go one step further and write a custom view helper. Because for any menu items with arrows, superfish wants the html to look like this:
<a href="#" class="sf-with-ul">menu item <span class="sf-sub-indicator"> »</span></a>
We'll create our custom View Helper in /library/My/View/Helper/Superfish.php. Start by specifying the path to your custom view helper in the Bootstrap.php _initNavigation() method, and go ahead and require the file:
//add custom helpers
require_once('My/View/Helper/Superfish.php');
$view->addHelperPath(
APPLICATION_ROOT . '/library/My/View/Helper/Navigation',
'My_View_Helper_'
);
We'll be extending Zend_View_Helper_Navigation_Menu, and the constructor looks like this:
class My_View_Helper_Superfish extends Zend_View_Helper_Navigation_Menu
{
public function superfish(Zend_Navigation_Container $container = null)
{
if (null !== $container) {
$this->setContainer($container);
}
return $this;
}
}
Because all the HTML markup changes are in the link rendering, the function we'll be overwriting is htmlify(). Basically we copy the htmlify function from Menu.php and then add a simple check for subpages, ending up with this:
public function htmlify(Zend_Navigation_Page $page)
{
(code from Menu.php)

// does page have subpages?
if ($page->count()) {
$sub_indicator = '<span class="sf-sub-indicator"> »</span>';
$attribs['class'] .= ' sf-with-ul';
} else {
$sub_indicator = '';
}

return '<' . $element . $this->_htmlAttribs($attribs) . '>'
. $this->view->escape($label)
. $sub_indicator
. '';
}
All you need to do to now use your superfish view helper is to call it in the layout.phtml instead of menu, like this:
echo $this->navigation()->superfish()->setUlClass('sf-menu');
Have fun playing around with the menus, adding new items, and reorganizing them to contain multiple levels, but as far as integrating superfish and Zend Framework is concerned, we're done. Happy coding!

Friday, June 11, 2010

Layout and Navigation, Part 2

In Part 1 of this series, I modified the ZF quickstart application to use Zend_Layout for an application-wide template. Part 2 will add a menu to the left sidebar of that template using Zend_Navigation.

Create a new file in the /application/configs directory called navigation.xml. Here is the content:
<?xml version="1.0" encoding="UTF-8"?>
<configdata>
<nav>
<content>
<label>Content Index</label>
<controller>content</controller>
<action>index</action>
<pages>
<page1>
<label>Page 1</label>
<controller>content</controller>
<action>page1</action>
</page1>
<page2>
<label>Page 2</label>
<controller>content</controller>
<action>page2</action>
</page2>
<page3>
<label>Page 3</label>
<controller>content</controller>
<action>page3</action>
</page3>
<page4>
<label>Page 4</label>
<controller>content</controller>
<action>page4</action>
</page4>
<page5>
<label>Page 5</label>
<controller>content</controller>
<action>page5</action>
</page5>
</pages>
</content>
</nav>
</configdata>
To use this XML file for creating the Zend_Menu requires adding an _initNavigation() function to the Bootstrap.php file. The Bootstrap file is a place to section out all the different application initialization methods. All of these are automatically run when $application->bootstrap()->run(); is called in index.php, or they can be selected and run individually (perhaps for other configurations such as web services or test) by calling $application->getBootstrap()->bootstrap('method_name'); at any time.

Here is the method you will want to add to initialize your navigation:
protected function _initNavigation()
{
// read in the xml menu
$xml = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');

// initialize the navigation object with the xml
$container = new Zend_Navigation($xml);

// Set the navigation object to the view
$view = Zend_Layout::getMvcInstance()->getView();
$view->navigation($container);
}
Now go back to your layout from Part 1 and replace the "menu goes here" text with this:
<?php
echo $this->navigation()->menu();
?>
One note here is that you should be developing in your development environment. If not, you will not get the errors and warning messages you may need to debug your menus. That is because the development section of application.ini includes these lines:
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1
Now that the navigation is loading correctly and the menus are rendering, lets add a breadcrumb to the header just to show how easy this is. Replace the Header div in layout.phtml with the following:
<div id="Header">
MySite:
<?php
echo $this->navigation()->breadcrumbs()->setMinDepth(0)->render();
?>
</div>
That's all for now. Happy coding!