Nathan Kelly
|
Thursday 06 July 2006 2:54:28 am
Hi Martin, I have worked on 2 sites now that require main (top) navigation and sub (bottom) navigation to be on the page at once and here are my solutions (you may need to customise, I have some extra variables etc. in there): Suckerfish menu (drop down)
<ul id="main-menu">
{def $home=fetch('content', 'node', hash('node_id', $topnode_id) )
$main_menu=fetch('content', 'list', hash('parent_node_id', 2,
'sort_by', array( array( 'priority' ) ),
'class_filter_type', include,
'class_filter_array', array( 'folder' ) ) ) }
{def $m_count=$main_menu|count|dec()}
{foreach $main_menu as $m_index => $m_menu}
<li{if eq($module_result.path[1].node_id,$m_menu.node_id)} class="current"{/if}{if $m_index|eq($m_count)} id="last"{/if}><a href={$m_menu.url_alias|ezurl}><span><span>{$m_menu.name}</span></span></a>
{def $sub_menu=fetch( 'content', 'list', hash( 'parent_node_id', $m_menu.node_id,
'sort_by', array( array( 'priority' ) ),
'class_filter_type', include,
'class_filter_array', array( 'folder', 'link' ) ) ) }
{def $s_count=$sub_menu|count|dec()}
{if $sub_menu|count|gt(0)}
<ul class="sub-menu">
{foreach $sub_menu as $s_index => $s_menu}
<li{if $s_index|eq($s_count)} class="last"{/if}><a href={$s_menu.url_alias|ezurl}>{$s_menu.name}</a></li>
{/foreach}
</ul>
{/if}
</li>
{/foreach}
{undef}
</ul>
Top main nav plus sidebar sub nav:
<!-- top (main nav) -->
<ul>
{def $home=fetch('content', 'node', hash('node_id', $topnode_id) )
$main_menu=fetch('content', 'list', hash('parent_node_id', 2,
'sort_by', array( array( 'priority' ) ),
'class_filter_type', include,
'class_filter_array', array('folder') ) ) }
{foreach $main_menu as $m_menu}
<li><a{if eq($module_result.path[1].node_id,$m_menu.node_id)} class="current"{/if} href={$m_menu.url_alias|ezurl}>{$m_menu.name}</a></li>
{/foreach}
{undef $home}
</ul>
<!-- sidebar (sub nav) -->
{def $sub_menu=treemenu($module_result.path, $module_result.node_id,
array('standard_page','folder','contact_form','sub_page','link'), 1, 2) }
<ul>
{def $last=0}
{foreach $sub_menu as $s_menu}
{if and($last|ne(0), $last.level|gt($s_menu.level))}{* this if second level is open *}
</ul>
</li>
{/if}
<li>
{if and($last|ne(0), $last.level|lt($s_menu.level))}{* this if there is no second level *}
<ul>
<li>{/if}<a{if $s_menu.is_selected} class="current"{/if} href={$s_menu.url_alias|ezurl}>{$s_menu.text}</a></li>
{set last=$s_menu}
{/foreach}
</ul>
{undef $last}
{undef $sub_menu}
This code produces the menus found at: http://www.ccts.com.au/ccts/construction/construction_services Hope this helps. Cheers!
Pardon me while I burst into flames...
|
Philipp Simon
|
Monday 10 July 2006 3:20:25 am
Hello guys! I rewrote the treemenu operator from scratch, so it does work recursively now. I tried to keep the old functionality, but "depth_skip" is now longer used. 'node_id' is now really used as start node. And last but not least I added an boolean value 'show_levels' to force the treemenu to show the whole subtree. Here is the code:
class eZTreeMenuOperator
{
/*!
*/
function eZTreeMenuOperator( $name = 'treemenu' )
{
$this->Operators = array( $name );
}
/*!
*/
function &operatorList()
{
return $this->Operators;
}
/*!
*/
function namedParameterList()
{
return array( 'path' => array( 'type' => 'array',
'required' => true,
'default' => false ),
'node_id' => array( 'type' => 'int',
'required' => true,
'default' => false ),
'class_filter' => array( 'type' => 'array',
'required' => false,
'default' => false ),
'depth_skip' => array( 'type' => 'int',
'required' => false,
'default' => false ),
'max_level' => array( 'type' => 'int',
'required' => false,
'default' => false ),
'show_levels' => array( 'type' => 'int',
'required' => false,
'default' => false ),
'is_selected_method' => array( 'type' => 'string',
'required' => false,
'default' => 'tree' ),
'indentation_level' => array( 'type' => 'int',
'required' => false,
'default' => 15 ),
'language' => array( 'type' => 'string|array',
'required' => false,
'default' => false ) );
}
/*!
*/
function modify( &$tpl, &$operatorName, &$operatorParameters, &$rootNamespace, &$currentNamespace, &$operatorValue, &$namedParameters )
{
$pathArray = array();
$tmpModulePath = $namedParameters[ 'path' ];
$indentationLevel = $namedParameters[ 'indentation_level' ];
$isSelectedMethod = $namedParameters[ 'is_selected_method' ];
$classFilter = $namedParameters[ 'class_filter' ];
$depthSkip = $namedParameters[ 'depth_skip' ];
$language = $namedParameters[ 'language' ];
$maxLevel = $namedParameters[ 'max_level' ];
$showLevels = $namedParameters[ 'show_levels' ];
$node_id = $namedParameters[ 'node_id' ];
if( $classFilter == 'false' )
{
$classFilter = array();
}
else if ( count( $classFilter ) == 0 )
{
$classFilter = array( 1 );
}
if ( $node_id === false )
{
$node_id = 2;
}
if ( $maxLevel === false )
{
$maxLevel = 2;
}
$cur_node_id = $node_id;
$cur_node = eZContentObjectTreeNode::fetch( $cur_node_id );
$cur_node_depth = $cur_node->attribute( "depth" );
$params = array();
$params[ 'Depth' ] = 1;
$params[ 'Offset' ] = 0;
$params[ 'SortBy' ] = $cur_node->sortArray();
$params[ 'Language' ] = $language;
$params[ 'ClassFilterType' ] = 'include';
$params[ 'ClassFilterArray' ] = $classFilter;
$cur_children = eZContentObjectTreeNode::subTree( $params, $cur_node_id );
eZContentObject::fillNodeListAttributes( $cur_children );
$this->traverseChildren( $cur_children, $tmpModulePath, $cur_node_depth, $maxLevel, $showLevels, $isSelectedMethod, $indentationLevel, $params, $pathArray );
$operatorValue = $pathArray;
}
/*!
*/
function traverseChildren( & $nodeArray, $modulePath, $rootDepth, $maxDepth, $showDepths, $isSelectedMethod, $indentationLevel, $params, & $pathArray )
{
$keys = array_keys( $nodeArray );
foreach ( $keys as $key )
{
$absDepth = $nodeArray[ $key ]->attribute( "depth" );
$relDepth = $absDepth - $rootDepth - 1;
$dataMap = $nodeArray[ $key ]->attribute( 'data_map' );
$contentObject = $nodeArray[ $key ]->attribute( 'object' );
$childrenCount = $nodeArray[ $key ]->attribute( 'children_count' );
$name = $nodeArray[ $key ]->attribute( 'name' );
$tmpNodeID = $nodeArray[ $key ]->attribute( 'node_id' );
$url = "/content/view/full/$tmpNodeID/";
$urlAlias = "/" . $nodeArray[ $key ]->attribute( 'url_alias' );
$mainNodeID = $nodeArray[ $key ]->attribute( 'main_node_id' );
$indent = $indentationLevel * ($relDepth+1);
$isMainNode = false;
if( $mainNodeID == $tmpNodeID )
{
$isMainNode = true;
}
$hasChildren = false;
if( $childrenCount > 0 )
{
$hasChildren = true;
}
$isActive = false;
$isSelected = false;
if( $modulePath[ $absDepth-1 ][ 'node_id' ] == $tmpNodeID )
{
$isActive = true;
if( $isSelectedMethod == 'tree' || count( $modulePath ) == $absDepth )
{
$isSelected = true;
}
}
$pathArray[] = array( 'id' => $nodeArray [ $key ]->attribute( "node_id" ),
'level' => $relDepth,
'data_map' => $dataMap,
'class_name' => $contentObject->classname(),
'is_main_node' => $isMainNode,
'has_children' => $hasChildren,
'indent' => $indent,
'url_alias' => $urlAlias,
'url' => $url,
'text' => $name,
'is_selected' => $isSelected,
'node' => $nodeArray [ $key ] );
if( $hasChildren && ( $showDepths || $isActive ) && ( $maxDepth > ($relDepth+1) ) )
{
$params[ 'SortBy' ] = $nodeArray[ $key ]->sortArray();
$subNodeArray = eZContentObjectTreeNode::subTree( $params, $tmpNodeID );
eZContentObject::fillNodeListAttributes( $subNodeArray );
if( $subNodeArray && count( $subNodeArray ) > 0 )
{
$this->traverseChildren( $subNodeArray, $modulePath, $rootDepth, $maxDepth, $showDepths, $isSelectedMethod, $indentationLevel, $params, $pathArray );
}
}
}
}
/// \privatesection
var $Operators;
};
And here is my test template for the left menu. I added support for internal as well as external links. (external opens a new window) And I added support for links like "ezNode://66", which will fetch the node and use its url_alias then. So when changing the target url, the link will still be valid. One word about the root node fetching. My menu looks like this:
- ROOT (ID=2)
- - Home (ID=80)
- - Service - - - Service 1 So when I am on the ROOT (entry site), I will fetch the menu of the folder "Home". I wanted to keep the url unchanged, but have an own home sidemenu. So whatever you do, you have to tweak this for your own use.
<div id="leftmenu">
<div id="leftmenu-design">
<h3 class="hide">{"Left menu"|i18n("design/base")}</h3>
<div class="toolbox">
<div class="toolbox-design">
{let $root_node=fetch( content, node, hash( node_id, is_set( $module_result.path[1].node_id )|choose( 80, $module_result.path[1].node_id ) ) )}
<h2>{$root_node.name}</h2>
<div class="toolbox-content">
{let docs=treemenu( $module_result.path,
$root_node.node_id,
ezini( 'MenuContentSettings', 'LeftIdentifierList', 'menu.ini' ),
0,
3,
true() )
depth=1
last_level=0}
<ul>
{section var=menu loop=$:docs last-value}
{set last_level=$menu.last|is_array|choose( $menu.level, $menu.last.level )}
{section show=and( $last_level|eq( $menu.level ), $menu.number|gt( 1 ) )}
</li>
{section-else}
{section show=and( $last_level|gt( $menu.level ), $menu.number|gt( 1 ) )}
</li>
{"</ul>
</li>"|repeat(sub( $last_level, $menu.level ))}
{/section}
{/section}
{section show=and( $last_level|lt( $menu.level ), $menu.number|gt( 1 ) )}
{'<ul><li>'|repeat(sub($menu.level,$last_level,1))}
<ul>
<li class="menu-level-{$menu.level}">
{section-else}
<li class="menu-level-{$menu.level}">
{/section}
{if eq( $menu.class_name, 'Link' )}
{def $link_content = $menu.node.object.data_map.location.content}
{if $link_content|contains( 'ezNode' )}
{def $tmpNodeParts = $link_content|explode( '//' )}
{def $tmpNodeId = $tmpNodeParts[ 1 ]}
{let $tmpNode=fetch( content, node, hash( node_id, $tmpNodeId ) )}
» <a href={$tmpNode.url_alias|ezurl}>{$menu.text|shorten( 25 )}</a>
{/let}
{undef $tmpNodeParts}
{undef $tmpNodeId}
{elseif $link_content|contains( 'http://' )}
» <a href={$link_content} target="_new">{$menu.text|shorten( 25 )}</a>
{else}
» <a href={$link_content|ezurl}>{$menu.text|shorten( 25 )}</a>
{/endif}
{else}
» <a {$menu.is_selected|choose( '', 'class="selected"' )} href={$menu.url_alias|ezurl}>{$menu.text|shorten( 25 )}</a>
{/endif}
{set depth=$menu.level}
{/section}
</li>
{section show=sub( $depth, 0 )|gt( 0 ) loop=sub( $depth, 0 )}
</ul>
</li>
{/section}
</ul>
{/let}
{/let}
</div>
</div>
</div>
</div>
</div>
<b>Although I did a fast test, I am not sure about bugs. So be careful using this code! If you find bugs, please report them to me.</b> Have fun! Phil
|