Skip to content
Permalink
Browse files

Menu: Overhauled menubar, again starting with Michael Lang's fork. Added

working keyboard navigation, including nested menus. Still need to
properly style the menu buttons, e.g. highlight the button of the
currently open menu.
  • Loading branch information...
jzaefferer committed Feb 22, 2011
1 parent 68c13cd commit f8091f761cf3705087efc90cc09f74e5f83744bb
Showing with 129 additions and 50 deletions.
  1. +8 −14 tests/visual/menu/flyoutmenu.js
  2. +28 −36 tests/visual/menu/menubar.html
  3. +93 −0 tests/visual/menu/menubar.js
@@ -34,14 +34,17 @@ $.widget("ui.flyoutmenu", {
}).keydown(function(event) {
if (self.element.is(":hidden"))
return;
event.stopPropagation();
switch (event.keyCode) {
case $.ui.keyCode.LEFT:
self.left(event);
if (self.left(event)) {
event.stopImmediatePropagation();
}
event.preventDefault();
break;
case $.ui.keyCode.RIGHT:
self.right(event);
if (self.right(event)) {
event.stopImmediatePropagation();
}
event.preventDefault();
break;
case $.ui.keyCode.ESCAPE:
@@ -98,29 +101,26 @@ $.widget("ui.flyoutmenu", {
at: "right top",
of: this.activeItem
});
$(document).one("click", function() {
//clicking outside menu flyouts should close all flyouts
//$(document).find(".ui-menu-flyout").hide();
})
},
_select: function(event) {
event.stopPropagation();
// TODO make _select cancelable?
this._trigger( "select", event, { item: this.activeItem } );
//this.activate(event, this.element.children("li").first());
this.hide();
},
left: function(event) {
var newItem = this.activeItem.parents("li").first();
if (newItem.length) {
this.activate(event, newItem);
return true;
}
},
right: function(event) {
var newItem = this.activeItem.children("ul").children("li").first();
if (newItem.length) {
this._open(newItem.parent());
this.activate(event, newItem);
return true;
}
},
activate: function(event, item) {
@@ -135,12 +135,6 @@ $.widget("ui.flyoutmenu", {
show: function() {
this.active = this.element;
this.element.show();
if (this.element.hasClass("ui-menu-flyout")) {
$(document).one("click", function() {
//clicking outside menu flyouts should close all flyouts
//$(document).find(".ui-menu-flyout").hide();
})
}
},
hide: function() {
this.activeItem = this.element.children("li").first();
@@ -10,7 +10,11 @@
<script type="text/javascript" src="../../../ui/jquery.ui.position.js"></script>
<script type="text/javascript" src="../../../ui/jquery.ui.button.js"></script>
<script type="text/javascript" src="../../../ui/jquery.ui.menu.js"></script>
<script type="text/javascript" src="flyoutmenu.js"></script>
<script type="text/javascript" src="menubar.js"></script>
<!--
<script type="text/javascript" src="http://jqueryui.com/themeroller/themeswitchertool/"></script>
-->
<script type="text/javascript">
$(function() {
$.fn.themeswitcher && $('<div/>').css({
@@ -19,45 +23,24 @@
top: 10
}).appendTo(document.body).themeswitcher();
$(".menubar").children("a")
.button()
.click(function() {
var button = $(this);
var menu = button.next();
if (menu.is(":visible")) {
menu.hide();
return false;
}
menu.parent().find(".ui-menu").not(menu).hide();
menu.show().css({ left:0, top: 0 }).position({
my: "left top",
at: "left bottom",
of: button
});
$(document).bind("click.menubar", function(event) {
if ($(event.target).closest(".ui-menu")[0] == menu[0]) {
return;
}
$(this).unbind(".menubar");
menu.hide();
});
return false;
})
.each(function() {
$(this).next().hide().menu({
input: $(this),
select: function(event, ui) {
$("<div/>").text("Selected: " + ui.item.text()).appendTo("#log");
}
});
});
$(".menubar").menubar({
select: function(event, ui) {
$("<div/>").text("Selected: " + ui.item.text()).appendTo("#log");
ui.item.parents("ul:last").prev().focus()
}
});
});
</script>
<style>
body { font-size:62.5%; }
.ui-menu { width: 200px; }
.menubar .ui-menu { position: absolute; }
.ui-menu { width: 200px; position: absolute; outline: none; }
.ui-menu .ui-icon { float: right; }
.ui-menu li.ui-state-disabled {
font-weight: bold;
padding: .0em .4em;
margin: .4em 0 .2em;
line-height: 1.5;
}
</style>
</head>
<body>
@@ -66,6 +49,7 @@
<a href="#">File</a>
<ul>
<li><a href="#">Open...</a></li>
<li class="ui-state-disabled">Open recent...</li>
<li><a href="#">Save</a></li>
<li><a href="#">Save as...</a></li>
<li><a href="#">Close</a></li>
@@ -75,12 +59,20 @@
<ul>
<li><a href="#">Copy</a></li>
<li><a href="#">Cut</a></li>
<li><a href="#">Paste</a></li>
<li class="ui-state-disabled">Paste</li>
</ul>
<a href="#">View</a>
<ul>
<li><a href="#">Fullscreen</a></li>
<li><a href="#">Fit into view</a></li>
<li>
<a href="#">Encoding</a>
<ul>
<li><a href="#">Auto-detect</a></li>
<li><a href="#">UTF-8</a></li>
<li><a href="#">UTF-16</a></li>
</ul>
</li>
<li><a href="#">Customize...</a></li>
</ul>
</div>
@@ -0,0 +1,93 @@
/*
* jQuery UI flyout menu
* - written for jQuery UI 1.9 milestone 2 using the widget factory
*
* Copyright (c) 2010 Michael Lang, http://nexul.com/
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
*/
(function($) {

$.widget("ui.menubar", {
_create: function() {
var self = this;
var items = this.element.children("button, a");
items.next("ul").each(function(i, elm) {
$(elm).flyoutmenu({
select: self.options.select
}).hide().addClass("ui-menu-flyout").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) {
if (menu.length && (!/^mouse/.test(event.type) || self.active && self.active.is(":visible") )) {
self._open(event, menu);
}
event.preventDefault();
event.stopPropagation();
}).button({
icons: {
secondary: menu.length ? 'ui-icon-triangle-1-s' : ''
}
});
});
$(document).click(function() {
!$(event.target).closest(".ui-menubar").length && items.next("ul").hide();
});
},

_open: function(event, menu) {
this.active && this.active.flyoutmenu("hide");
this.active = menu.flyoutmenu("show").css({
position: "absolute",
top: 0,
left: 0
}).position({
my: "left top",
at: "left bottom",
offset: "0 -1",
of: menu.prev()
}).focus();
},

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

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

}(jQuery));

0 comments on commit f8091f7

Please sign in to comment.
You can’t perform that action at this time.