Wednesday, January 27, 2016

Accordion-Like Navigation Menu

By default, it's only possible to expend the side navigation menu children submenu by clicking on the corresponding down arrow.

Here's how you can do if you would like to be able to do the same thing by simply clicking on the list entry text.

On your page 0, create a new dynamic action on page load that is going to run one the following javascript code depending on the target type you have on your list entry
Use this one if you set your target type to URL and your URL target to #
$('#t_Body_nav #t_TreeNav li.a-TreeView-node--topLevel > div.a-TreeView-content:has(a[href="#"])').click(function(){
   $(this).prev('span.a-TreeView-toggle').click();
});
Use this one if you set your target type to - No Target -
$('#t_Body_nav #t_TreeNav li.a-TreeView-node--topLevel > div.a-TreeView-content:not(:has(a))').click(function(){
   $(this).prev('span.a-TreeView-toggle').click();
});
This is going to look at all the top level list entries and if their link is equal to "#" (or if the entry has no link), it's going to trigger the arrow's click event when you click on the list entry text.
So basically, when you click on the text, it's going to be clicking on the arrow as well.

EDIT: If you want to use this for a multi-level menu, the javascript dynamic action code will need to be changed. After debug it, I found out that the submenu items are generated dynamically when expanding it's parent. So the click event from the above code is not registered for the new li tags. We need to
Use this one if you set your target type to URL and your URL target to #
$('#t_Body_nav #t_TreeNav').on('click', 'ul li.a-TreeView-node div.a-TreeView-content:has(a[href="#"])', function(){
   $(this).prev('span.a-TreeView-toggle').click();
});
Use this one if you set your target type to - No Target -
$('#t_Body_nav #t_TreeNav').on('click', 'ul li.a-TreeView-node div.a-TreeView-content:not(:has(a))', function(){
   $(this).prev('span.a-TreeView-toggle').click();
});

You can have a look at my Demo Application

6 comments:

  1. Hi Maxime,

    Thanks for your hint. It worked greatly..!

    Kind Regards,
    Bhavin

    ReplyDelete
  2. Interesting use case and solution. Note that if the navigation list entry has no target there is no anchor. You could change the code to handle this but whenever possible it is better to use APIs rather than rely on markup. Try the following

    $("#t_TreeNav").on("treeviewactivatenode", function(e, ui) {
    var n$ = $(e.originalEvent.target).closest(".a-TreeView-content");
    if (ui.nodes.length > 0 && ui.nodes[0].link === "") {
    if (n$.parent().hasClass("is-expandable")) {
    $(this).treeView("expand", n$)
    } else if (n$.parent().hasClass("is-collapsible")) {
    $(this).treeView("collapse", n$)
    }
    }
    });

    Even though the treeView API is not supported it is less likely to change than the internal markup details. However the above does still rely on some classes.

    Also may be of interest the treeView option doubleClick: "toggle".

    ReplyDelete
    Replies
    1. I updated the code for when there is no anchor.
      I'll have a look at the event approach.
      Thanks

      Delete
  3. Hi Maxime, when do you have this behaviour? When I try it on apex.world the menu opens not matter if you click on the text or the arrow?

    ReplyDelete
    Replies
    1. The behaviour I describe was for the side navigation menu. I updated the post to clarify. I also added an animated image to show the end result.

      Delete