Details
-
Type:
Improvement
-
Status:
Open
-
Priority:
Trivial
-
Resolution: Unresolved
-
Affects Version/s: 1.8.0, 1.8.1, 1.8.2
-
Fix Version/s: Next Mini Release
-
Component/s: Zend_Navigation, Zend_View
-
Tags:
Description
I want an option to display the menu with all sibling of the active branch and not just the parents branch.
For the exemple in the view helpers documentation display the menu like this :
- Foo Server
- FAQ
- Editions
- System Requirement
- Foo Studio
- Investor Relations
- News
- My Account
- Forums
The code changed in the Menu helper, I had a new option parameter : "expandBranch"
/**
* Whether only active branch should be rendered
*
* @var bool
*/
protected $_expandBranch = false;
/**
* Sets a flag indicating whether the first depth and expand the active branch
*
* @param bool $flag [optional] render the first depth and the active branch
* . Default is true.
* @return Zend_View_Helper_Navigation_Menu fluent interface, returns self
*/
public function setExpandBranch($flag = true)
{
$this->_expandBranch = (bool) $flag;
return $this;
}
/**
* Returns a flag indicating whether the first depth and the active branch should be rendered
*
* By default, this value is false, meaning the entire menu will be
* be rendered.
*
* @return bool whether only active branch should be rendered
*/
public function getExpandBranch()
{
return $this->_expandBranch;
}
// Render methods:
/**
* Renders a normal menu (called from {@link renderMenu()})
*
* @param Zend_Navigation_Container $container container to render
* @param string $ulClass CSS class for first UL
* @param string $indent initial indentation
* @param int|null $minDepth minimum depth
* @param int|null $maxDepth maximum depth
* @param bool $onlyActive render only active branch?
* @param bool $expandBranch render sibling of the active branch
* @return string
*/
protected function _renderMenu(Zend_Navigation_Container $container,
$ulClass,
$indent,
$minDepth,
$maxDepth,
$onlyActive,
$expandBranch)
{
$html = '';
// find deepest active
if ($found = $this->findActive($container, $minDepth, $maxDepth)) {
$foundPage = $found['page'];
$foundDepth = $found['depth'];
} else {
$foundPage = null;
}
// create iterator
$iterator = new RecursiveIteratorIterator($container,
RecursiveIteratorIterator::SELF_FIRST);
if (is_int($maxDepth)) {
$iterator->setMaxDepth($maxDepth);
}
// iterate container
$prevDepth = -1;
foreach ($iterator as $page) {
$depth = $iterator->getDepth();
$isActive = $page->isActive(true);
if ($depth < $minDepth || !$this->accept($page)) {
// page is below minDepth or not accepted by acl/visibilty
continue;
} else if ($expandBranch && $depth > $minDepth) { // If expand branch
// page is not active itself, but might be in the active branch
$accept = false;
if ($foundPage) {
if ($foundPage->hasPage($page)) {
// accept if page is a direct child of the active page
$accept = true;
} else if ($page->getParent()->isActive(true)) {
// page is a sibling of the active branch...
$accept = true;
}
}
if (!$isActive && !$accept) {
continue;
}
} else if ($onlyActive && !$isActive) {
// page is not active itself, but might be in the active branch
$accept = false;
if ($foundPage) {
if ($foundPage->hasPage($page)) {
// accept if page is a direct child of the active page
$accept = true;
} else if ($foundPage->getParent()->hasPage($page)) {
// page is a sibling of the active page...
if (!$foundPage->hasPages() ||
is_int($maxDepth) && $foundDepth + 1 > $maxDepth) {
// accept if active page has no children, or the
// children are too deep to be rendered
$accept = true;
}
}
}
if (!$accept) {
continue;
}
}
// make sure indentation is correct
$depth -= $minDepth;
$myIndent = $indent . str_repeat(' ', $depth);
if ($depth > $prevDepth) {
// start new ul tag
if ($ulClass && $depth == 0) {
$ulClass = ' class="' . $ulClass . '"';
} else {
$ulClass = '';
}
$html .= $myIndent . '<ul' . $ulClass . '>' . self::EOL;
} else if ($prevDepth > $depth) {
// close li/ul tags until we're at current depth
for ($i = $prevDepth; $i > $depth; $i--) {
$ind = $indent . str_repeat(' ', $i);
$html .= $ind . ' </li>' . self::EOL;
$html .= $ind . '</ul>' . self::EOL;
}
// close previous li tag
$html .= $myIndent . ' </li>' . self::EOL;
} else {
// close previous li tag
$html .= $myIndent . ' </li>' . self::EOL;
}
// render li tag and page
$liClass = $isActive ? ' class="active"' : '';
$html .= $myIndent . ' <li' . $liClass . '>' . self::EOL
. $myIndent . ' ' . $this->htmlify($page) . self::EOL;
// store as previous depth for next iteration
$prevDepth = $depth;
}
if ($html) {
// done iterating container; close open ul/li tags
for ($i = $prevDepth+1; $i > 0; $i--) {
$myIndent = $indent . str_repeat(' ', $i-1);
$html .= $myIndent . ' </li>' . self::EOL
. $myIndent . '</ul>' . self::EOL;
}
$html = rtrim($html, self::EOL);
}
return $html;
}
/**
* Renders helper
*
* Renders a HTML 'ul' for the given $container. If $container is not given,
* the container registered in the helper will be used.
*
* Available $options:
*
*
* @param Zend_Navigation_Container $container [optional] container to
* create menu from. Default
* is to use the container
* retrieved from
* {@link getContainer()}.
* @param array $options [optional] options for
* controlling rendering
* @return string rendered menu
*/
public function renderMenu(Zend_Navigation_Container $container = null,
array $options = array())
{
if (null === $container) {
$container = $this->getContainer();
}
$options = $this->_normalizeOptions($options);
if ($options['onlyActiveBranch'] && !$options['renderParents']) {
$html = $this->_renderDeepestMenu($container,
$options['ulClass'],
$options['indent'],
$options['minDepth'],
$options['maxDepth']);
} else {
$html = $this->_renderMenu($container,
$options['ulClass'],
$options['indent'],
$options['minDepth'],
$options['maxDepth'],
$options['onlyActiveBranch'],
$options['expandBranch']);
}
return $html;
}
I just had this condition before the activeBranch condition :
if ($expandBranch && $depth > $minDepth) { // If expand branch // page is not active itself, but might be in the active branch $accept = false; if ($foundPage) { if ($foundPage->hasPage($page)) { // accept if page is a direct child of the active page $accept = true; } else if ($page->getParent()->isActive(true)) { // page is a sibling of the active branch... $accept = true; } } if (!$isActive && !$accept) { continue; } }
Attachments
Issue Links
| This issue is related to: | ||||
| ZF-8317 | Zend_View_Helper_Navigation_Menu renderSiblings() |
|
|
|
Thanks for the detailed report. I see how this feature might be useful.
Have you signed a CLA? Would you care to implement the expandBranch feature and write tests and docs for it? You probably have a better overview of exactly what needs to be tested etc.