r3424 committed - menu: nested menu refactoring, for now as its own widget
Revision: 3424
Author: joern.zaefferer
Date: Mon Nov 9 05:11:21 2009
Log: menu: nested menu refactoring, for now as its own widget
http://code.google.com/p/jquery-ui/source/detail?r=3424
Modified:
/branches/dev/tests/visual/menu/nested.html
=======================================
--- /branches/dev/tests/visual/menu/nested.html Mon Nov 9 03:10:32 2009
+++ /branches/dev/tests/visual/menu/nested.html Mon Nov 9 05:11:21 2009
@@ -9,67 +9,98 @@
<script type="text/javascript"
src="../../../ui/jquery.ui.core.js"></script>
<script type="text/javascript"
src="../../../ui/jquery.ui.menu.js"></script>
<script type="text/javascript"
src="../../../ui/jquery.ui.position.js"></script>
- <script type="text/javascript"
src="http://jqueryui.com/themeroller/themeswitchertool/"></script>
<script type="text/javascript">
$(function() {
- $.fn.themeswitcher && $('<div/>').css({
- position: "absolute",
- right: 10,
- top: 10
- }).appendTo(document.body).themeswitcher();
-
-
- var submenu;
- var menu = $("#menu").menu({
+ $.widget("ui.nestedmenu", {
+ _init: function() {
+ var self = this;
+ this.active = this.element;
+
+ // hide submenus and create indicator icons
+ this.element.find("ul").hide().prev("a").prepend('<span class="ui-icon
ui-icon-carat-1-e"></span>');
+
+ this.element.find("ul").andSelf().menu({
+ selected: this.options.selected,
+ focus: function(event, ui) {
+ self.active = ui.item.parent();
+ // put a previous submenu back into its place and hide it
+ self.hideDown();
+ var nested = $(">ul", ui.item);
+ if (nested.length) {
+ // append to body in order to display the submenu above the parent
menu, instead of inside of it
+ nested.appendTo(document.body).menu("deactivate").show().position({
+ my: "left top",
+ at: "right top",
+ of: ui.item
+ // store the current submenu
+ }).data("menuparent", ui.item);
+
+ self.active.data("submenu", nested);
+ }
+ }
+ })
+ },
+
+ up: function() {
+ if (!this.active.data("menuparent"))
+ return;
+ this.active.menu("deactivate");
+ this.active = this.active.data("menuparent").parent();
+ },
+
+ down: function() {
+ var submenu = this.active.data("submenu");
+ if (!submenu)
+ return;
+ submenu.data("menu").activate(submenu.children(":first"))
+ this.active = submenu;
+ },
+
+ show: function() {
+ this.element.menu("deactivate").show();
+ this.active = this.element;
+ },
+
+ hide: function() {
+ this.hideDown();
+ var child = this.active.hide(), parent;
+ while(child.data("menuparent")) {
+ parent = child.data("menuparent");
+ child.appendTo(parent).removeData("menuparent");
+ child = parent.parent().removeData("submenu").hide();
+ }
+ },
+
+ hideDown: function() {
+ var submenu = this.active.data("submenu");
+ while(submenu) {
+ var parent = submenu.data("menuparent");
+ submenu.appendTo(parent).hide().removeData("menuparent");
+ parent.parent().removeData("submenu");
+ submenu = submenu.data("submenu");
+ };
+ }
+ });
+
+ var nestedmenu = $("#menu").nestedmenu({
selected: function(event, ui) {
$("#log").append("<div>Selected " + ui.item.text() + "</div>");
- },
- focus: function(event, ui) {
- // put a previous submenu back into its place and hide it
- if (submenu) {
- submenu.appendTo(submenu.data("menuparent")).hide();
- submenu = null;
- }
- var nested = $("ul", ui.item);
- if (nested.length) {
- nested.menu({
- selected: function(event, ui) {
- $("#log").append("<div>Selected " + ui.item.text() + "</div>");
- }
- // append to body in order to display the submenu above the parent
menu, instead of inside of it
- }).appendTo(document.body).menu("deactivate").show().position({
- my: "left top",
- at: "right top",
- of: ui.item
- });
- // store the current submenu
- submenu = nested;
- submenu.data("menuparent", ui.item);
- }
}
}).hide();
- // hide submenus and create indicator icons
- menu.find("ul").hide().prev("a").prepend('<span class="ui-icon
ui-icon-carat-1-e"></span>');
-
-
$("button").click(function(event) {
// TODO required to prevent the click handler below from handling this
event
event.stopPropagation();
- $("#menu").menu("deactivate").show().position({
+ nestedmenu.nestedmenu("show").position({
my: "left top",
at: "right top",
of: event.pageX > 0 ? event : this
});
$().one("click", function() {
- menu.hide();
- if (submenu) {
- submenu.appendTo(submenu.data("menuparent")).hide();
- submenu = null;
- }
+ nestedmenu.nestedmenu("hide");
})
}).keydown(function(event) {
- var menu = submenu && submenu.data("menufocussed") &&
submenu.data("menu") || $("#menu" + this.id).data("menu");
+ var menu = nestedmenu.data("nestedmenu").active.data("menu");
if (menu.widget().is(":hidden"))
return;
event.stopPropagation();
@@ -84,17 +115,10 @@
menu.previous();
break;
case $.ui.keyCode.LEFT:
- if (submenu && submenu.data("menufocussed")) {
- submenu.data("menufocussed", false);
- menu.deactivate();
- }
+ nestedmenu.nestedmenu("up");
break;
case $.ui.keyCode.RIGHT:
- if (submenu) {
- submenu.data("menufocussed", true);
- menu = submenu.data("menu");
- menu.activate(menu.element.children(":first"));
- }
+ nestedmenu.nestedmenu("down");
break;
case $.ui.keyCode.DOWN:
menu.next();
@@ -103,25 +127,11 @@
case $.ui.keyCode.ENTER:
case $.ui.keyCode.TAB:
menu.select();
- menu.widget().hide();
- if (submenu) {
- submenu.appendTo(submenu.data("menuparent"));
- submenu.removeData("menuparent");
- submenu = null;
- // also hide parent
- $("#menu" + this.id).hide();
- }
+ nestedmenu.nestedmenu("hide");
event.preventDefault();
break;
case $.ui.keyCode.ESCAPE:
- menu.widget().hide();
- if (submenu) {
- submenu.appendTo(submenu.data("menuparent"));
- submenu.removeData("menuparent");
- submenu = null;
- // also hide parent
- $("#menu" + this.id).hide();
- }
+ nestedmenu.nestedmenu("hide");
break;
default:
clearTimeout(menu.filterTimer);
@@ -177,7 +187,23 @@
<ul>
<li><a href="#">Aberdeen</a></li>
<li><a href="#">Ada</a></li>
- <li><a href="#">Adamsville</a></li>
+ <li>
+ <a href="#">Adamsville</a>
+ <ul>
+ <li><a href="#">Anaheim</a></li>
+ <li>
+ <a href="#">Cologne</a>
+ <ul>
+ <li><a href="#">Mberdeen</a></li>
+ <li><a href="#">Mda</a></li>
+ <li><a href="#">Mdamsville</a></li>
+ <li><a href="#">Mddyston</a></li>
+ <li><a href="#">Mmesville</a></li>
+ </ul>
+ </li>
+ <li><a href="#">Frankfurt</a></li>
+ </ul>
+ </li>
<li><a href="#">Addyston</a></li>
<li><a href="#">Amesville</a></li>
</ul>