Wednesday, May 2, 2012

Controlling Wijmo Context Menu Display

The Wijmo menu widget can do some really neat things.  For one, it is flexible in that it can behave as a regular navigational menu, or as a context menu.  The context menu is especially handy and bridges a rather large gap in jQuery UI.  It isn't without it's limitations though.

Wijmo menu items can change dynamically.  We would put this capability to use when menu items should be hidden due to the state of another object, for example. The menu API allows the developer to easily add and remove items.  However, the challenge lies with controlling whether or not the context menu should be displayed at all.  For instance, if all menu items have been removed, for one reason or another.  This is where we need to take precaution because the menu has no built-in display control.

Example
Let's look at a trivial example where can add and remove items from a context menu dynamically.  This includes the possibility of emptying the menu, at which point, it shouldn't be displayed.

The HTML...

<body>
    <button id="btnmenu">Show Menu</button>
    <button id="btnadd">Add Item</button>
    <button id="btnremove">Remove Item</button>
    <ul id="menu">
        <li><a href="#">Item 1</a></li>
        <li><a href="#">Item 2</a></li>
        <li><a href="#">Item 3</a></li>
    </ul>
</body>

The Javascript...

$(document).ready(function () {

    $('#btnmenu').button().click(function (event) {

        if ($('#menu').find('li').length === 0) {

            event.stopImmediatePropagation();

        }

    });
    
    $('#btnadd').button().click(function (event) {
    
        var menu      = $('#menu'),
            itemCount = menu.find('li').length,
            itemText  = 'Item ' + (itemCount + 1),
            itemLink  = $('<a>').attr('href', '#').text(itemText);
    
        menu.append($('<li/>').append(itemLink))
            .wijmenu('refresh');

    });

    $('#btnremove').button().click(function (event) {

        $('#menu').find('li').last().remove();

    });

    $('#menu').wijmenu({

        orientation: 'vertical',
        trigger:     '#btnmenu'

    });

});

This will create three buttons.  The first will display the context menu when clicked. The second button will add a new item to the context menu, and the last button will remove an item.  The intent behind the add and remove buttons is to control how the context menu is displayed.  You can remove items until the menu is empty.  At this point, the context menu will not display until you add a new item.


Explanation
The key take-away here is the click event on the show menu button.  This event handler is how we're able to control the context menu display based on some logic. In our case, we don't want to display the menu if there aren't any items in it.  But I'm sure there are other use cases where overriding the context menu display would be beneficial.

The other thing to note is how we're actually stopping the context menu from displaying.  We're calling event.stopImmediatePropagation().  Since this event handler is the first one executed when the button is clicked, no other handlers will be executed if the menu is empty.  This includes the context menu trigger.