jquery-ui/tests/visual/menu/flyoutmenu.js
jzaefferer 355705878a Menu: Overhauled nested menu via flyoutmenu.js backported from Michael
Lang's fork. Changed key input handling by setting focus to menu,
getting rid of input option.
2011-02-22 11:51:08 +01:00

150 lines
4.2 KiB
JavaScript

/*
* jQuery UI flyout menu
* - written for jQuery UI 1.9 milestone 2 using the widget factory
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* modified from: http://view.jqueryui.com/menu/tests/visual/menu/nested.html
* by: Michael Lang, http://nexul.com/
*
*/
(function($) {
$.widget("ui.flyoutmenu", {
_create: function() {
var self = this;
this.active = this.element;
this.activeItem = this.element.children("li").first();
// hide submenus and create indicator icons
this.element.find("ul").addClass("ui-menu-flyout").hide().prev("a").prepend('<span class="ui-icon ui-icon-carat-1-e"></span>');
this.element.find("ul").andSelf().menu({
select: function(event) {
self._select(event);
},
focus: function(event, ui) {
self.active = ui.item.parent();
self.activeItem = ui.item;
ui.item.parent().find("ul").hide();
var nested = $(">ul", ui.item);
if (nested.length && event.originalEvent && /^mouse/.test(event.originalEvent.type)) {
self._open(nested);
}
}
}).keydown(function(event) {
if (self.element.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.ESCAPE:
self.hide();
break;
default:
clearTimeout(self.filterTimer);
var prev = self.previousFilter || "";
var character = String.fromCharCode(event.keyCode);
var skip = false;
if (character == prev) {
skip = true;
} else {
character = prev + character;
}
var match = self.activeItem.parent("ul").children("li").filter(function() {
return new RegExp("^" + character, "i").test($("a", this).text());
});
var match = skip && match.index(self.active.next()) != -1 ? match.next() : match;
if (!match.length) {
character = String.fromCharCode(event.keyCode);
match = self.widget().children("li").filter(function() {
return new RegExp("^" + character, "i").test($(this).text());
});
}
if (match.length) {
self.activate(event, match);
if (match.length > 1) {
self.previousFilter = character;
self.filterTimer = setTimeout(function() {
delete self.previousFilter;
}, 1000);
} else {
delete self.previousFilter;
}
} else {
delete self.previousFilter;
}
}
});
},
_open: function(submenu) {
// TODO restrict to widget
//only one menu can have items open at a time.
$(document).find(".ui-menu-flyout").not(submenu.parents()).hide();
submenu.show().css({
top: 0,
left: 0
}).position({
my: "left top",
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);
}
},
right: function(event) {
var newItem = this.activeItem.children("ul").children("li").first();
if (newItem.length) {
this._open(newItem.parent());
this.activate(event, newItem);
}
},
activate: function(event, item) {
if (item) {
item.parent().data("menu").widget().show();
item.parent().data("menu").activate(event, item);
}
this.activeItem = item;
this.active = item.parent("ul")
this.active.focus();
},
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();
this.element.find("ul").andSelf().menu("deactivate").hide();
}
});
}(jQuery));