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