Magento – Varien_Data_Tree_Node – Position nav menu items

navigationrwdvarien

Digging into the 1.9 RWD nav menu, I am fiddling with Varien_Data_Tree and Varien_Data_Tree_Node – I haven't worked with these classes directly before and they seem unfinished as there are several empty methods in the classes.

Using an observer on the page_block_html_topmenu_gethtml_before event, I am able to add a new item to the menu using:

    $event = $observer->getEvent();
    $menu = $event->getMenu();
    $nodeData = array(
        'name'      => 'My Node',
        'id'        => 'my_node',
        'url'       => 'My-Url.html',
        'is_active' => false
        );
    $node = new Varien_Data_Tree_Node($nodeData, 'my-node', new Varien_Data_Tree());
    $menu->addChild($node);

As expected, I see a new nav menu item on the front-end listed after any other nav items already built; however, I would like to position this node so that it is shown before or after any other items (such as how before="-" after="-" are used in layout XML).

How can I adjust the position of items added to the nav menu in this fashion?

Best Answer

Marius to the rescue! Its not an elegant solution but seems to be the only approach. Since its a matter of getting the existing tree items, temporarily storing the data, removing them and then readding the existing items with the newly inserted one before.

Taken from: https://magento.stackexchange.com/a/7361/69

public function addItemsToTopmenuItems($observer){
    //get the menu object -Type Varien_Data_Tree_Node
    $menu = $observer->getMenu();
    //get the tree object in the menu -type Varien_Data_Tree
    $tree = $menu->getTree();
    //get current page handler
    $action = Mage::app()->getFrontController()->getAction()->getFullActionName();
    $brandNodeId = 'category-node-brand';
    //set the node id, label and url
    $data = array(
        'name' => Mage::helper('catalog')->__('Brands'),
        'id' => $brandNodeId,
        'url' => Mage::getUrl('brands'),
        'is_active' => ($action == 'brands')
    );
    //create a node object
    $brandNode = new Varien_Data_Tree_Node($data, 'id', $tree, $menu);
    //temporary array with nodes
    $menuItems = array();
    //my first menu item
    $menuItems[] = $brandNode;
    //loop through existing menu items, add them to the array and remove them from the    menu
    foreach ($menu->getChildren() as $child){
        //add the item to the temp array
        $menuItems[] = $child;
        //remove item from the menu
        $menu->removeChild($child);
        //I need to add a new menu item after the category with id 6
        //don't worry the id is not hard coded. it comes from a config setting
        //I just added 6 here to make it easier to read
        if ($child->getId() == 'category-node-6'){
            //create a new node as $brandNode called $newNode
            ...
            //add the node to my temp array
            $menuItems[] = $newNode;
        }
    }
    //add other nodes at the end of my temp array
    ...
    //recreate the menu in the order I need
    foreach ($menuItems as $child){
        $menu->addChild($child);
    }
}

Also it may be worth mentioning that Varien_Data_Tree_Node_Collection implements ArrayAccess.

Related Topic