some more menu and keyboard navigation

This commit is contained in:
Rolux 2010-02-05 14:43:03 +05:30
parent 88057655f0
commit 150c3df7b6
2 changed files with 198 additions and 60 deletions

View file

@ -47,7 +47,6 @@ requires
}(),
path: $("script[src*=ox.ui.js]").attr("src")
.replace("js/ox.ui.js", ""),
stack: [], // fixme: used?
symbols: { // fixme: make lowercase
alt: "\u2325",
apple: "\uF8FF",
@ -203,21 +202,52 @@ requires
// use dom elements / jquery instead
Ox.Event = function() {
var $eventHandler = $("<div>");
var keyboardEvents = {};
$eventHandler = $("<div>");
function isKeyboardEvent(event) {
return event.substr(0, 4) == "key_";
}
return {
bind: function(event, callback) {
$eventHandler.bind(event, callback);
bind: function(id, event, callback) {
if (isKeyboardEvent(event)) {
keyboardEvents[id] = keyboardEvents[id] || [];
keyboardEvents[id].push({
event: event,
callback: callback
});
}
if (!isKeyboardEvent(event) || Ox.Focus.focused() == id) {
$eventHandler.bind(event, callback);
}
},
one: function(event, callback) {
$eventHandler.one(event, callback);
bindKeyboard: function(id) {
$.each(keyboardEvents[id] || [], function(i, event) {
Ox.Event.bind(id, event.event, event.callback);
});
},
trigger: function(event, data) {
Ox.print("trigger", event, data || {});
$eventHandler.trigger(event, data || {});
},
unbind: function(event, callback) {
unbind: function(id, event, callback) {
if (isKeyboardEvent(event)) {
$.each(keyboardEvents[id] || [], function(i, e) {
if (e.event == event) {
keyboardEvents[id].splice(i, 1);
return false;
}
});
}
$eventHandler.unbind(event, callback);
},
unbindKeyboard: function(id) {
//Ox.print(keyboardEvents)
//Ox.print("unbindKeyboard", id, keyboardEvents[id])
$.each(keyboardEvents[id] || [], function(i, e) {
$eventHandler.unbind(e.event, e.callback);
});
}
}
}();
@ -265,14 +295,31 @@ requires
var stack = [];
return {
focus: function(id) {
/*
if (stack.length) {
Ox.Event.unbindKeyboard(stack[stack.length - 1]);
}
*/
var index = stack.indexOf(id);
if (index > -1) {
oxui.stack.splice(i, 1);
stack.splice(index, 1);
}
oxui.stack.push(id);
stack.push(id);
Ox.Event.bindKeyboard(id);
console.log("focus", stack);
},
focused: function() {
return stack[stack.length - 1];
},
blur: function(id) {
oxui.stack.pop();
if (stack.indexOf(id) > -1) {
stack.splice(stack.length - 2, 0, stack.pop());
}
Ox.Event.unbindKeyboard(id);
/*
Ox.Event.bindKeyboard(stack[stack.length - 1]);
*/
console.log("blur", stack);
}
};
}();
@ -438,7 +485,7 @@ requires
buffer += key == "SPACE" ? " " : key;
bufferTime = time;
}
Ox.Event.trigger("key." + key);
Ox.Event.trigger("key_" + key);
/*
$.each(stack, function(i, v) {
// fixme: we dont get the return value!
@ -656,7 +703,6 @@ requires
};
}();
/*
----------------------------------------------------------------------------
Ox.URL
@ -771,20 +817,35 @@ requires
};
// public
that.bindEvent = function() {
/*
bindEvent(event, fn) or bindEvent({event0: fn0, event1: fn1, ...})
*/
if (arguments.length == 1) {
$.each(arguments[0], function(event, fn) {
Ox.Event.bind(that.id, event, fn);
})
} else {
Ox.Event.bind(that.id, arguments[0], arguments[1]);
}
};
that.defaults = function(defaults) {
/*
that.defaults({foo: x}) sets self.defaults
*/
self.defaults = defaults;
return that;
}
that.gain = function() {
Ox.Focus.gain(that.id);
}
that.lose = function() {
Ox.Focus.lose(that.id);
}
that.options = function() {
};
that.gainFocus = function() {
Ox.Focus.focus(that.id);
};
that.hasFocus = function() {
return Ox.Focus.focused() == that.id;
};
that.loseFocus = function() {
Ox.Focus.blur(that.id);
};
that.options = function() { // fixme: use Ox.getset
/*
that.options() returns self.options
that.options("foo") returns self.options.foo
@ -817,26 +878,21 @@ requires
}
return ret;
}
that.publish = function() {
arguments[0] = arguments[0] + "." + that.id;
Ox.Event.publish.apply(that, arguments);
// or, maybe better:
$(".OxWidget").trigger.apply(that, arguments);
return that;
}
that.remove = function() {
that.$element.remove();
delete elements[that.ox];
}
that.subscribe = function() {
Ox.Event.subscribe.apply(that, arguments);
// or
that.$element.bind.apply(that, arguments);
return that;
}
that.unsubscribe = function() {
Ox.Event.unsubscribe.apply(that, arguments);
return that;
that.unbindEvent = function() {
/*
unbindEvent(event, fn) or unbindEvent({event0: fn0, event1: fn1, ...})
*/
if (arguments.length == 1) {
$.each(arguments[0], function(event, fn) {
Ox.Event.unbind(that.id, event, fn);
})
} else {
Ox.Event.unbind(that.id, arguments[0], arguments[1]);
}
}
// return
@ -1694,9 +1750,10 @@ requires
left: 0,
top: 0
},
parent: null,
selected: -1,
side: "bottom",
size: "medium"
size: "medium",
})
.options(options)
.addClass(
@ -1740,8 +1797,9 @@ requires
left: 0,
top: -4
},
parent: that,
side: "right",
size: self.options.size
size: self.options.size,
});
}
} else {
@ -1756,6 +1814,12 @@ requires
.addClass("OxBottom")
.appendTo(that.$element);
function click(event) {
if (!$(event.target).is(".OxCell")) {
that.hideMenu();
}
}
function clickItem() {
if (self.options.selected > -1) {
that.items[self.options.selected].trigger("click");
@ -1823,6 +1887,7 @@ requires
}
function getElement(id) {
// fixme: needed?
return $("#" + Ox.toCamelCase(options.id + "/" + id));
}
@ -1898,6 +1963,37 @@ requires
}
}
function selectSubmenu() {
var submenu = that.submenus[that.items[self.options.selected].options("id")];
if (submenu && submenu.hasEnabledItems()) {
that.loseFocus();
submenu.gainFocus();
submenu.selectFirstItem();
}
}
function selectSupermenu() {
if (self.options.parent) {
that.items[self.options.selected].trigger("mouseleave");
that.loseFocus();
self.options.parent.gainFocus();
}
}
self.onChange = function(key, value) {
}
that.hasEnabledItems = function() {
var ret = false;
$.each(that.items, function(i, item) {
if (!item.options("disabled")) {
return ret = true;
}
});
return ret;
};
that.hideMenu = function() {
Ox.print("hideMenu")
$.each(that.submenus, function(i, submenu) {
@ -1911,11 +2007,20 @@ requires
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.escape", that.hideMenu);
Ox.Event.unbind("key.enter", clickItem);
$document.unbind("click", that.hideMenu);
that.loseFocus();
that.unbindEvent({
key_up: selectPreviousItem,
key_down: selectNextItem,
key_left: selectSupermenu,
key_right: selectSubmenu,
key_escape: that.hideMenu,
key_enter: clickItem
});
$document.unbind("click", click);
};
that.selectFirstItem = function() {
selectNextItem();
};
that.showMenu = function() {
@ -1935,13 +2040,19 @@ 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.escape", that.hideMenu);
Ox.Event.bind("key.enter", clickItem);
if (!self.options.parent) {
that.gainFocus();
}
that.bindEvent({
key_up: selectPreviousItem,
key_down: selectNextItem,
key_left: selectSupermenu,
key_right: selectSubmenu,
key_escape: that.hideMenu,
key_enter: clickItem
});
setTimeout(function() {
$document.bind("click", that.hideMenu);
$document.bind("click", click);
}, 100);
};
@ -2025,7 +2136,7 @@ requires
);
function click() {
if (!that.hasClass("OxDisabled") && !self.options.submenu) {
if (!that.hasClass("OxDisabled") && !self.options.items.length) {
self.options.menu.hideMenu();
if (self.options.checked !== null && (!self.options.group || !self.options.checked)) {
that.options({
@ -2039,7 +2150,6 @@ requires
id: self.options.id,
value: self.options.title // fixme: value or title?
});
return false;
}
}
@ -2050,7 +2160,10 @@ requires
function mouseenter() {
if (!self.options.disabled && !isSelected()) {
$.each(self.options.menu.submenus, function(id, submenu) {
submenu.hideMenu();
if (!submenu.is(":hidden")) {
submenu.hideMenu();
return false;
}
});
if (self.options.menu.options("selected") > -1) {
self.options.menu.items[self.options.menu.options("selected")].trigger("mouseleave");

View file

@ -74,18 +74,43 @@ $(function() {
},
],
title: "More",
},
{
id: "even_more",
items: [
{
checked: true,
group: "101112",
id: "tenth",
title: "Tenth"
},
{
checked: false,
group: "101112",
id: "eleventh",
title: "Eleventh"
},
{
checked: false,
group: "101112",
id: "twelfth",
title: "Twelfth"
},
],
title: "Even More",
}
]
});
button.click(function() {
$(this).blur(); // fix for firefox
menu.toggleMenu();
});
Ox.Event.bind("OxClickMenu", function(event, data) {
button.options({
value: data.value
button
.click(function() {
$(this).blur(); // fix for firefox
menu.toggleMenu();
})
.bindEvent("OxClickMenu", function(event, data) {
button.options({
value: data.value
});
});
});
$select = $("<select>")
.css({
position: "absolute",