From 28ceec3bc20b9f76799d2b3f1d1bf786f9a58f8b Mon Sep 17 00:00:00 2001 From: Rolux Date: Thu, 4 Feb 2010 15:20:45 +0530 Subject: [PATCH] some keyboard navigation for menus --- build/js/ox.ui.js | 189 ++++++++++++++++++++++++++++----------------- demos/test/menu.js | 11 ++- 2 files changed, 122 insertions(+), 78 deletions(-) diff --git a/build/js/ox.ui.js b/build/js/ox.ui.js index 89804da..2e3d8cf 100644 --- a/build/js/ox.ui.js +++ b/build/js/ox.ui.js @@ -108,7 +108,7 @@ requires $document = $(document), $body = $("body"); Ox.theme(oxui.defaultTheme); - }) + }); /* ============================================================================ @@ -209,14 +209,18 @@ requires bind: function(event, callback) { $eventHandler.bind(event, callback); }, - trigger: function(event, data) { - $eventHandler.trigger(event, data); + one: function(event, callback) { + $eventHandler.one(event, callback); }, - unbind: function(event) { + trigger: function(event, data) { + Ox.print("trigger", event, data || {}); + $eventHandler.trigger(event, data || {}); + }, + unbind: function(event, callback) { $eventHandler.unbind(event, callback); } } - } + }(); Ox.Event_ = function() { var events = {}; @@ -324,32 +328,32 @@ requires 55: "7", 56: "8", 57: "9", - 65: "A", - 66: "B", - 67: "C", - 68: "D", - 69: "E", - 70: "F", - 71: "G", - 72: "H", - 73: "I", - 74: "J", - 75: "K", - 76: "L", - 77: "M", - 78: "N", - 79: "O", - 80: "P", - 81: "Q", - 82: "R", - 83: "S", - 84: "T", - 85: "U", - 86: "V", - 87: "W", - 88: "X", - 89: "Y", - 90: "Z", + 65: "a", + 66: "b", + 67: "c", + 68: "d", + 69: "e", + 70: "f", + 71: "g", + 72: "h", + 73: "i", + 74: "j", + 75: "k", + 76: "l", + 77: "m", + 78: "n", + 79: "o", + 80: "p", + 81: "q", + 82: "r", + 83: "s", + 84: "t", + 85: "u", + 86: "v", + 87: "w", + 88: "x", + 89: "y", + 90: "z", 91: "meta.left", 92: "meta.right", 93: "select", @@ -408,39 +412,41 @@ requires shiftKey: "shift" }; - return function() { - document.keydown(keydown); - function keydown(e) { - var key = [], - ret = true, - time; - $.each(modifierNames, function(k, v) { - if (e[k]) { - key.push(v); - } - }); - // avoid pushing modifier twice - if (keyNames[e.keyCode] && keys.indexOf(keyNames[e.keyCode]) == -1) { - key.push(keyNames[e.keyCode]); + $(function() { + $document.keydown(keydown); + }); + function keydown(event) { + var key, + keys = [], + ret = true, + time; + $.each(modifierNames, function(k, v) { + if (event[k]) { + keys.push(v); } - key = key.join(" "); - if (key.match(/^[\w\d-]$|SPACE/)) { - time = Ox.time(); - if (time - bufferTime > bufferTimeout) { - buffer = ""; - } - buffer += key == "SPACE" ? " " : key; - bufferTime = time; - } - $.each(stack, function(i, v) { - // fixme: we dont get the return value! - ret = Ox.event.publish(keyboard + Ox.toCamelCase(key) + "." + v); - return ret; - }); - + }); + // avoid pushing modifier twice + if (keyNames[event.keyCode] && keys.indexOf(keyNames[event.keyCode]) == -1) { + keys.push(keyNames[event.keyCode]); } - - }; + key = keys.join("."); + if (key.match(/^[\w\d-]$|SPACE/)) { + time = Ox.getTime(); + if (time - bufferTime > bufferTimeout) { + buffer = ""; + } + buffer += key == "SPACE" ? " " : key; + bufferTime = time; + } + Ox.Event.trigger("key." + key); + /* + $.each(stack, function(i, v) { + // fixme: we dont get the return value! + ret = Ox.event.trigger(keyboard + Ox.toCamelCase(key) + "." + v); + return ret; + }); + */ + } })(); @@ -1650,6 +1656,7 @@ requires left: 0, top: 0 }, + selected: -1, side: "bottom", size: "medium" }) @@ -1659,7 +1666,6 @@ requires " Ox" + Ox.toTitleCase(self.options.size) ), itemHeight = options.size == "small" ? 12 : (options.size == "medium" ? 16 : 20), - selected = -1, scrollSpeed = 1, $item; @@ -1687,10 +1693,9 @@ requires menu: that, submenu: that.submenus[item.id] || null }); - item = new Ox.MenuItem(item) - .data("pos", i) - .appendTo(that.$content); - that.items.push(item); + that.items.push(new Ox.MenuItem($.extend(item, { + position: that.items.length + })).appendTo(that.$content)); that.$content.append($item); } else { that.$content.append(constructSpace()); @@ -1704,6 +1709,12 @@ requires .addClass("OxBottom") .appendTo(that.$element); + function clickItem() { + if (self.options.selected > -1) { + that.items[self.options.selected].trigger("click"); + } + } + function constructLine() { return $("").append( $("", { @@ -1795,11 +1806,23 @@ requires } function selectNextItem() { - + var selected = self.options.selected; + if (selected < that.items.length - 1) { + if (selected > -1) { + that.items[selected].trigger("mouseleave"); + } + selected++; + that.items[selected].trigger("mouseenter"); + } } function selectPreviousItem() { - + var selected = self.options.selected; + if (selected > 0) { + that.items[selected].trigger("mouseleave"); + selected--; + that.items[selected].trigger("mouseenter"); + } } that.hideMenu = function() { @@ -1812,6 +1835,13 @@ requires }); // fixme: scroll menu back up! that.hide(); + if (self.options.selected > -1) { + that.items[self.options.selected].trigger("mouseleave"); + } + Ox.Event.unbind("key down", selectNextItem) + Ox.Event.unbind("key up", selectPreviousItem) + Ox.Event.unbind("key.enter", clickItem); + $document.unbind("click", that.hideMenu); }; that.showMenu = function() { @@ -1831,6 +1861,13 @@ requires that.$container.height(maxHeight - itemHeight); that.$scrollbars.down.show(); } + Ox.print("binding...") + Ox.Event.bind("key.down", selectNextItem); + Ox.Event.bind("key.up", selectPreviousItem); + Ox.Event.bind("key.enter", clickItem); + setTimeout(function() { + $document.bind("click", that.hideMenu); + }, 100); }; that.toggleMenu = function() { @@ -1855,6 +1892,7 @@ requires id: "", keyboard: "", menu: null, // fixme: is passing the menu to 100s of menu items really memory-neutral? + position: 0, submenu: null, title: [], }) @@ -1867,9 +1905,10 @@ requires id: Ox.toCamelCase(self.options.menu.id + "/" + self.options.id) }) .click(click) - .data("group", self.options.group) + .data("group", self.options.group) // fixme: why? .mouseenter(mouseenter) - .mouseleave(mouseleave); + .mouseleave(mouseleave) + .mousemove(mouseenter); // in case selection has goes elsewhere via keyboard // construct that.append( @@ -1921,7 +1960,7 @@ requires if (self.options.title.length == 2) { that.toggleTitle(); } - $("*").trigger("OxClickMenu", { + Ox.Event.trigger("OxClickMenu", { id: self.options.id, value: self.options.title // fixme: value or title? }); @@ -1937,12 +1976,18 @@ requires $(".OxMenu .OxItem[id!=" + self.options.id + "]").removeClass("selected"); self.options.submenu && self.options.submenu.showMenu(); // fixme: do we want to switch to this style? that.addClass("OxSelected"); + self.options.menu.options({ + selected: self.options.position + }); } } function mouseleave() { if (!that.hasClass("OxDisabled") && !self.options.submenu) { that.removeClass("OxSelected"); + self.options.menu.options({ + selected: -1 + }); } } diff --git a/demos/test/menu.js b/demos/test/menu.js index 45ac183..c9b0fca 100644 --- a/demos/test/menu.js +++ b/demos/test/menu.js @@ -51,13 +51,12 @@ $(function() { } ] }); - button - .click(menu.toggleMenu) - .bind("OxClickMenu", function(event, data) { - button.options({ - value: data.value - }); + button.click(menu.toggleMenu) + Ox.Event.bind("OxClickMenu", function(event, data) { + button.options({ + value: data.value }); + }); $select = $("