3

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?

3

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.

  • Don't know how I missed that question. This is pretty much what I was suspecting I would need to do. – pspahn Nov 13 '14 at 20:05
  • I feel like there might be a better solution if a simple sort_order is added to each node and then rearrange the menu's array inside the topmenu/renderer.phtml template based on sort_order. – pspahn Nov 13 '14 at 20:06
  • May offer a better elogant solution: github.com/OpenMage/magento-mirror/blob/magento-1.9/lib/Varien/… – B00MER Nov 13 '14 at 20:15
  • 1
    @B00MER. The move method you linked works for tree behavior with links to the database. It would be nice to have such a method for non-db related trees. – Marius Nov 14 '14 at 7:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.