2

I'm looking for some multiple vertical menu such here. I don't want any drop menu. I'm using in my mysql database typical closure table hierarchy (ancestor/descendant/depth) for categories and I want to render they. To get all parents and childrens from database I have these methods:

   public function getSubtree($node) {
    $tree = $this->connection->query("
    SELECT c.*, cc2.ancestor, cc2.descendant, cc.depth
    FROM
        category c
        JOIN category_closure cc
        ON (c.cat_id = cc.descendant)
            JOIN category_closure cc2
            USING (descendant)
    WHERE cc.ancestor = $node AND cc2.depth = 1
    ORDER BY cc.depth, c.cat_id);

    return $this->parseSubTree($node, $tree);
}

private function parseSubTree($rootID, $nodes) {
    // to allow direct access by node ID
    $byID = array();

    // an array of parrents and their children
    $byParent = array();


    foreach ($nodes as $node) {
        if ($node["cat_id"] != $rootID) {
            if (!isset($byParent[$node["ancestor"]])) {
                $byParent[$node["ancestor"]] = array();
            }
            $byParent[$node["ancestor"]][] = $node["cat_id"];
        }
        $byID[$node["cat_id"]] = (array) $node;
    }

    // tree reconstruction
    $tree = array();
    foreach ($byParent[$rootID] as $nodeID) { // root direct children
        $tree[] = $this->parseChildren($nodeID, $byID, $byParent);
    }

    return $tree;
}

private function parseChildren($id, $nodes, $parents) {
    $tree = $nodes[$id];

    $tree["children"] = array();
    if (isset($parents[$id])) {
        foreach ($parents[$id] as $nodeID) {
            $tree["children"][] = $this->parseChildren($nodeID, $nodes, $parents);
        }
    }

    return $tree;
}

In presenter I have just:

$this->template->categories = $this->category->getSubtree(1);

And because I'm using the Nette Framework, I'm using Latte template engine, such is very similar with Smarty. For render all categories with parents and childrens I have this:

    <ul class="tree">
    {block #categories}
        {foreach $categories as $node}
            <li>
                <span">{$node["name"]}</span>
                <ul n:if="count($node['children'])">
                    {include #categories, 'categories' => $node["children"]}
                </ul>
            </li>
        {/foreach}
    {/block}
</ul>

My biggest problem is how to make css style if I want three and more level menu. If is selected some category is his subcategories shown and another categories hide. When is picked some subcategories is showing his subcategories and another subcategories hide and so on. Really thanks for advance and I'm sorry for my english. Hope you know what i mean.

Jaroslav Klimčík
  • 4,548
  • 12
  • 39
  • 58

2 Answers2

1

If I understand it well you want a drop-down menu. The alignment is vertical I guess. The subcategories, should they render under the category or beside? I understand that the rest should remain visible.

imNeku
  • 11
  • 1
  • I just want simple collapsible vertical menu which render all under. If some category is current another categories should remain hidden but its subcategory should be visible. – Jaroslav Klimčík Jul 17 '13 at 07:00
0

If you want it purely vertical you should work with an onclick and JavaScript. If it is with mousse overs try this:

ul {

width: 200px;
position: relative;
list-style: none;
margin: 0;
padding: 0;

}

ul li {

background: #ccc;
border-bottom: 1px solid #fff;
position: relative;

}

ul li ul {

position: absolute;
left: 200;
top: 0;
display: none;

}

ul li:hover ul {

display: block;

}

ul li ul li {

border-left: 1px solid #fff;

}

imNeku
  • 11
  • 1