jQuery UI menubar: how to activate from keyboard
Asked Answered
P

2

7

jQuery UI menubar from jqueryui.com git master allows keyboard navigation if it is active.

I'm looking for a way to activate menubar from keyboard. I tried code below. Right Alt / AltGr key is catched. However arrow keys are still ignored in menu. It looks like first bar menu pad should be opened for keyboard navigation to take effect or something similar. How to activate menu from keyboard so keyboard can used without need for mouse click?

    <head><script type="text/javascript">
    $(function () {
    $(document).bind('keyup', function (event) {
       var keycode = (event.keyCode ? event.keyCode : event.which);
     if (keycode === 17) { // 17 = Right ALT / AltrGR
         $("#bar1").focus();
     }
     });
     </script></head>


    <body>
    <div id="container">
    <div id="bar1">
        <% Html.RenderAction("Menu", "Home"); %>
    </div>
    <div id="main">
        <asp:ContentPlaceHolder ID="MainContent" runat="server" />
    </div>
    </div>
    </body>

UPDATE

According Pehmolelu answer it looks like first submenu from menubar should activated. Menubar.js code from jQuery UI tests is below. How to find and activate first menu bar so that keyboard keys can used to navigate ?

/*
 * jQuery UI menubar
 *
 * backported from Michael Lang's fork:        
 http://www.nexul.com/prototypes/toolbar/demo.html
 */
(function($) {

// TODO take non-menubar buttons into account
$.widget("ui.menubar", {
options: {
  buttons: false,
  menuIcon: false
},
_create: function() {
  var self = this;
  var items = this.items = this.element.children("button, a");
  var o = this.options;

  this.element.addClass('ui-menubar ui-widget-header ui-helper-clearfix');

items.next("ul").each(function(i, elm) {
        $(elm).menu({
            select: function(event, ui) {
                ui.item.parents("ul:last").hide()
                self.options.select.apply(this, arguments);
            }
        }).hide().keydown(function(event) {
            var menu = $(this);
            if (menu.is(":hidden")) 
                return;
            event.stopPropagation();
            switch (event.keyCode) {
            case $.ui.keyCode.LEFT:
                self.left(event);
                event.preventDefault();
                break;
            case $.ui.keyCode.RIGHT:
                self.right(event);
                event.preventDefault();
                break;
            case $.ui.keyCode.TAB:
                self[ event.shiftKey ? "left" : "right" ]( event );
                event.preventDefault();
                break;
            };
        });
    });
    items.each(function() {
        var input = $(this),
               menu = input.next("ul");

        input.bind("click focus mouseenter", function(event) {
            event.preventDefault();
            event.stopPropagation();
            if (menu.is(":visible") && self.active && self.active[0] == menu[0]) {
                self._close();
                return;
            }
            if (menu.length && (!/^mouse/.test(event.type) || self.active && self.active.is(":visible") )) {
                self._open(event, menu);
            }
        })
        .addClass("ui-button ui-widget ui-button-text-only ui-menubar-link")
        .wrapInner("<span class='ui-button-text'></span>");
        self._hoverable(input)

        if (o.menuIcon) {
            input.addClass("ui-state-default").append("<span class='ui-button-icon-secondary ui-icon ui-icon-triangle-1-s'></span>");
            input.removeClass("ui-button-text-only").addClass("ui-button-text-icon-secondary");
        }

        if (!o.buttons) {
            input.addClass('ui-menubar-link').removeClass('ui-state-default');
        };          

    });
    $(document).click(function(event) {
        !$(event.target).closest(".ui-menubar").length && self._close();
    });
},

_close: function() {
    this.items.next("ul").hide();
    this.items.removeClass("ui-state-active");
},

_open: function(event, menu) {
    if (this.active) {
        this.active.menu("closeAll").hide();
        this.active.prev().removeClass("ui-state-active");
    }
    var button = menu.prev().addClass("ui-state-active");
    this.active = menu.show().position({
        my: "left top",
        at: "left bottom",
        of: button
    }).focus();
},

left: function(event) {
    var prev = this.active.prevAll( ".ui-menu" ).eq( 0 );
    if (prev.length) {
        this._open(event, prev);
    } else {
        this._open(event, this.element.children(".ui-menu:last"));
    }
},

right: function(event) {
    var next =  this.active.nextAll( ".ui-menu" ).eq( 0 );
    if (next.length) {
        this._open(event, next);
    } else {
        this._open(event, 
this.element.children(".ui- menu:first"));
    }
}
});

}(jQuery));
Polston answered 28/5, 2011 at 21:21 Comment(0)
H
1

Div elements can receive focus only if you put tabindex attribute to them.

<div id="bar1" tabindex="1">

But div elements are not really compatible with tabindex by definition: http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex

You should probably try to focus on other element inside that div to see how it works.

Edit:

Without really knowing the actual menubar at all, I have a hunch. In the beginning it is defined that:

var items = this.items = this.element.children("button, a");

So you are selecting all buttons and anchros as items. Then at lower there is this items.each in which you bind click focus and mouseenter events to each item.

So I would try focusing to a button or anchor item.

Hoi answered 20/6, 2011 at 7:8 Comment(1)
Thank you. I added tabindex='1' to menubar div. In this case div receives focus on keypress (dotted rectangle appears around div). Howewer keyboard keys still cannot used to navigate in menu and menu does not receive focus (no items are hightlighted). I added menubar code from jQueryUYI to question. How to activate firt submenu in menubar or is there other way to enable navigation in menu ?Polston
C
1

Try calling .focus() on the first menu item from inside the function that opens the menu. For example:

$("#menu").find("[role=menuitem]")[0].focus();

This works, but has a cosmetic issue. When the arrow keys are used to change menu selections, an orange focus halo is left around the first item. Other than that it seems to work as expected

I tried using the .menu("focus") method instead, but as you probably already found, the focus is taken away again a split second later -- I think because the mouse is not inside the menu area.

Cherida answered 7/10, 2015 at 2:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.