0

I am hoping to get some advice. Basically I have menu items stored in an array, any item may have it's own sub menu items. I am trying to figure out how I can keep track of which menu (array) a user is currently scrolling through. The end goal would be a user using keys on the keyboard can go from item to item and if it has a sub menu they could access those items if they chose. The following code is how my menu items are stored. I appreciate any advice, thank you!

var menu = [{
    "title": "Home",
    "link": "/index.jsp"
}, {
    "title": "Our Company",
    "link": "javascript:;",
    "subMenu": [{
        "title": "Employees",
        "link": "/employees"
        }, {
        "title": "Investors →",
        "link": "/invest",
        "subMenu": [{
            "title": "News",
            "link": "/invest/news"
        }, {
            "title": "History",
            "link": "/invest/history"
        }]
    }, {
        "title": "xyz",
        "link": "/xyz"
    }, {
        "title": "xyz",
        "link": "/xyz"
    }, {
        "title": "xyz",
        "link": "/xyz"
    }, {
        "title": "xyz",
        "link": "/xyz/"
    }]
}, {
    "title": "Human Resources",
    "link": "javascript:;",
    "subMenu": [{
        "title": "Apply",
        "link": "/apply"
    }, {
        "title": "Information",
        "link": "/info"
    }, {
        "title": "Complaints",
        "link": "/complains"
    }]
}];

As of right now I just have a variable with a number that I increase / decrease when pressing keys on the board. I know I can check to see if subMenu exists for any item when they access it, I'm just having trouble wrapping my head around keeping track of the parent item when accessing sub menus, etc.

Should I be thinking instead about using another array to keep track of the menu items the user is currently on? and pushing / popping them out of there as they navigate through?

1
  • Not sure how you are creating the DOM elements for the given menu, but you can probably rely on DOM hierarchy for knowing current selection (active element), parent, children etc. If you are using / ready to use JQuery, it might become simpler. Commented Feb 22, 2017 at 2:00

1 Answer 1

1

Addding a tree structure with linkages is one way of solving the problem.

Navigation proceeds by using the arrow keys to select the next, or previous item in a menu (relative to the current item), or go up to the item containing the current submenu, or go down to the first item in a submenu belonging to the current item if it exists.

Concept code:

function linkMenu( menu, parent = null)
{ menu.parentItem = parent;
  menu.firstItem = menu[0] || null;
  menu.lastItem = menu[menu.length-1] || null
  menu.forEach(function( item,i, menu) {
    item.parentMenu = menu;                  // update
    item.previousItem = menu[i-1] || null;
    item.nextItem = menu[i+1] || null;
    if( item.subMenu) {
       linkMenu(item.subMenu,  item);
       item.firstChildItem = item.subMenu.firstItem || null;
    }
  });
}

which using the posted menu definition gives the following example result

linkMenu(menu)
menu.firstItem.nextItem.firstChildItem.nextItem.title; // Investors →

This kind of of linkage is typical of tree structures in general but there are choices: navigation could wrap around first and last items if desired, and an actual application may not need all the linkages setup or amend them as required - say to make the submenu an item is in easier to get at.


Processing arrow keys requires knowledge of the visual model, but say for example that

  • main menu is horizontal
  • submenus are vertical
  • submenus of submenus are vertical and cascade to the right
  • currentItem points to the currently selected menu item
  • closeSubMenu and openSubMenu are functions that take an item parameter.
  • mainMenu is the boolean result of the expression (!currenItem.parentItem)

Pseudo code for arrow processing could resemble

Left Arrow:

if( mainMenu) currentItem = currentItem.previousItem || currentItem;
else closeSubMenu( currentItem.parentItem),
     currentItem = currentItem.parentMenu.parentItem);  // update

Right Arrow:

if(mainMenu) currentItem = currentItem.nextItem || currentItem;
else if( currenItem.firstChildItem)
    openSubMenu( currentItem),
    currentItem = current.firstChildItem;

Down Arrow:

if mainMenu && currentItem.firstChildItem)
    openSubMenu( currentItem),
    currentItem = current.firstChildItem;
else if(!mainMenu)
    currentItem = currentItem.nextChild || currentItem;

Up Arrow:

if( mainMenu) ; // do nothing
else currentItem = currentItem.previousChild || currerntItem;

Visually highlighting has not been included. It may help if focus is passed to the current item after arrow key processing.

Sign up to request clarification or add additional context in comments.

7 Comments

Thank you, this seems like what I need. I am still having trouble understanding how I would go about navigating the items with this linkage? From the start, pressing right multiple times should result in "Home" > "Our Company" > "Human Resources". Pressing Down from either Our Company or Human Resources would enter those sub menus, if a link within a submenu has another submenu, right arrow would access it, etc. Thanks again for your time.
@RON2015 some thoughts in the updated answer. It can get more complicated if you want to faithfully reproduce Window type menu navigation. Happy coding :-)
Thank you so much for the update, I am getting close. Is there a problem with the linkMenu function though? It seems like it is not getting submenu's of submenus. It is only getting the first "main menu" and their submenus.
Sorry, disregard the last comment I made, the sub-submenus are being added but it seems like the parentItem is always undefined when trying to navigate
My bad. Items did not know what menu they were in. I've added it as item.parentMenu which should have been opened from item.parentMenu.parentItem.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.