Multi-level horizontal navigation menu

Login or register to post comments
7 replies [Last post]
void's picture
Offline
Joined: 07/25/2008

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

Offline
Joined: 08/12/2009

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.

alex94040's picture
Offline
Joined: 11/06/2008

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 :-)

void's picture
Offline
Joined: 07/25/2008

Ok; thanks a lot for your answers.

scottux's picture
Offline
Joined: 11/07/2008

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;
    }
}
?>

alex94040's picture
Offline
Joined: 11/06/2008

Scott - do you want to wrap up these two interesting controls into a plugin?

scottux's picture
Offline
Joined: 11/07/2008

Yes, I have been meaning to. I'll try to get to that ASAP.

void's picture
Offline
Joined: 07/25/2008

Wow! Cool Scott! Thanks!