Multi-level horizontal navigation menu
Mon, 07/26/2010 - 09:00
Hi,
Does anyone know can i create a multi-level horizontal navigation menu (like this one for example: http://csscreator.com/tools/multimenu) using QCubed?
Thanks

the closest thing QCubed has is QNavTree, but I think you'd be better off iterating over your data and build the menu using plain PHP and then apply the needed JS script.
Also, I'd look for a jQuery plugin that would build this sort of thing. There's quite a few available today: http://plugins.jquery.com/project/Plugins/category/44.
QCubed can be used to populate the contents of the menu (server-side), but the actual looks / functionality of the menu is very much a javascript thing. The good news is that jQuery is already included with your QCubed install :-)
Ok; thanks a lot for your answers.
Here are two QControls that may help:
<?php
class QUnorderedList extends QControl {
protected $_arrList = array();
// Because we're generating a Block Element (at its core, the control is a
// DIV with a bunch of stuff inside), let's set this to true.
// (This is required for X/HTML Strict Standards Compliance)
protected $blnIsBlockElement = true;
/**
* If this control needs to update itself from the $_POST data, the logic to do so
* will be performed in this method.
*/
public function ParsePostData() {}
/**
* If this control has validation rules, the logic to do so
* will be performed in this method.
* @return boolean
*/
public function Validate() {return true;}
/**
* Get the HTML for this Control.
* @return string
*/
public function GetControlHtml() {
// Pull any Attributes
$strAttributes = $this->GetAttributes();
// Pull any styles
if ($strStyle = $this->GetStyleAttributes())
$strStyle = 'style="' . $strStyle . '"';
return sprintf('<div id="%s" %s%s>%s</div>',$this->strControlId, $strAttributes, $strStyle,$this->HTMLList($this->_arrList));
}
/**
* Constructor for this control
* @param mixed $objParentObject Parent QForm or QControl that is responsible for rendering this control
* @param string $strControlId optional control ID
*/
public function __construct($objParentObject, $strControlId = null) {
try {
parent::__construct($objParentObject, $strControlId);
} catch (QCallerException $objExc) { $objExc->IncrementOffset(); throw $objExc; }
}
public function AddListItem($array) {
try {
$this->_arrList = array_merge_recursive($this->_arrList , $array);
} catch (QCallerException $objExc) { $objExc->IncrementOffset(); throw $objExc; }
}
public function HTMLList($array) {
if (!is_array($array)) return $array;
if (empty($array)) return '';
$list = '<ul>'."\n";
foreach ($array as $k => $v)
$list .= '<li class="item'.$k.'">'.$this->HTMLList($v).'</li>'."\n";
$list .= '</ul>'."\n";
return $list;
}
}
?>
And then:
<?php
class QMenu extends QUnorderedList {
public $menu;
protected $itemCounter = 0;
/**
* If this control needs to update itself from the $_POST data, the logic to do so
* will be performed in this method.
*/
public function ParsePostData() {}
/**
* If this control has validation rules, the logic to do so
* will be performed in this method.
* @return boolean
*/
public function Validate() {return true;}
/**
* Get the HTML for this Control.
* @return string
*/
public function GetControlHtml() {
$array = $this->menu;
// Pull any Attributesarray(
$strAttributes = $this->GetAttributes();
// Pull any styles
if ($strStyle = $this->GetStyleAttributes())
$strStyle = 'style="' . $strStyle . '"';
// Start Output of QMenu
$out = sprintf("\t".'<ul id="%s" %s%s>'."\r\n", $this->strControlId, $strAttributes, $strStyle);
for ( $i = 1; $i <= count( $array ); $i++ ) {
if ( is_array( $array[$i] ) ) {
if ( $array[$i]['show'] && $array[$i]['parent'] == 0 ) {
$out .= "\t\t".'<li class="parentMenu"><span><a href="' . $array[$i]['link'] . '">';
$out .= $array[$i]['label'];
$out .= '</a></span>';
$out .= $this->getChildren( $array, $i );
$out .= '</li>' . "\r\n";
}
} else {
$objExc->IncrementOffset();
throw $objExc;
}
}
$out .= "\t</ul>\r\n";
// This should return a wonderful list suitable for a site navigation menu
return $out;
}
/**
* Constructor for this control
* @param mixed $objParentObject Parent QForm or QControl that is responsible for rendering this control
* @param string $strControlId optional control ID
*/
public function __construct($objParentObject, $strControlId = null) {
try {
parent::__construct($objParentObject, $strControlId);
} catch (QCallerException $objExc) { $objExc->IncrementOffset(); throw $objExc; }
}
public function AddItem($objItem) {
}
public function AddMenuItem($label, $link= '#', $parent = 0, $show = TRUE) {
$this->itemCounter++;
try {
$this->menu[$this->itemCounter] = array(
'label' => $label,
'link' => $link,
'parent'=> $parent,
'show' => $show
);
} catch (QCallerException $objExc) { $objExc->IncrementOffset(); throw $objExc; }
}
public function getChildren( $array, $id ){
$isChild = FALSE;
$out = "\t<ul>\r\n";
for ( $i = 1; $i <= count( $array ); $i++ ){
if ( $array[$i]['show'] && $array[$i]['parent'] == $id ) {
$isChild = TRUE;
$out .= "\t\t".'<li class="childMenu"><span><a href="'.$array[$i]['link'].'">'.$array[$i]['label'].'</a>' . $this->getChildren( $array, $i ) . "</span></li>\r\n";
}
}
$out .= "\t</ul>\r\n";
return($isChild) ? $out : FALSE;
}
}
?>
Scott - do you want to wrap up these two interesting controls into a plugin?
Yes, I have been meaning to. I'll try to get to that ASAP.
Wow! Cool Scott! Thanks!