some more menu and keyboard navigation
This commit is contained in:
parent
88057655f0
commit
150c3df7b6
2 changed files with 198 additions and 60 deletions
|
@ -47,7 +47,6 @@ requires
|
||||||
}(),
|
}(),
|
||||||
path: $("script[src*=ox.ui.js]").attr("src")
|
path: $("script[src*=ox.ui.js]").attr("src")
|
||||||
.replace("js/ox.ui.js", ""),
|
.replace("js/ox.ui.js", ""),
|
||||||
stack: [], // fixme: used?
|
|
||||||
symbols: { // fixme: make lowercase
|
symbols: { // fixme: make lowercase
|
||||||
alt: "\u2325",
|
alt: "\u2325",
|
||||||
apple: "\uF8FF",
|
apple: "\uF8FF",
|
||||||
|
@ -203,21 +202,52 @@ requires
|
||||||
|
|
||||||
// use dom elements / jquery instead
|
// use dom elements / jquery instead
|
||||||
|
|
||||||
|
|
||||||
Ox.Event = function() {
|
Ox.Event = function() {
|
||||||
var $eventHandler = $("<div>");
|
var keyboardEvents = {};
|
||||||
|
$eventHandler = $("<div>");
|
||||||
|
function isKeyboardEvent(event) {
|
||||||
|
return event.substr(0, 4) == "key_";
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
bind: function(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);
|
$eventHandler.bind(event, callback);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
one: function(event, callback) {
|
bindKeyboard: function(id) {
|
||||||
$eventHandler.one(event, callback);
|
$.each(keyboardEvents[id] || [], function(i, event) {
|
||||||
|
Ox.Event.bind(id, event.event, event.callback);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
trigger: function(event, data) {
|
trigger: function(event, data) {
|
||||||
Ox.print("trigger", event, data || {});
|
Ox.print("trigger", event, data || {});
|
||||||
$eventHandler.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);
|
$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 = [];
|
var stack = [];
|
||||||
return {
|
return {
|
||||||
focus: function(id) {
|
focus: function(id) {
|
||||||
|
/*
|
||||||
|
if (stack.length) {
|
||||||
|
Ox.Event.unbindKeyboard(stack[stack.length - 1]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
var index = stack.indexOf(id);
|
var index = stack.indexOf(id);
|
||||||
if (index > -1) {
|
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) {
|
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;
|
buffer += key == "SPACE" ? " " : key;
|
||||||
bufferTime = time;
|
bufferTime = time;
|
||||||
}
|
}
|
||||||
Ox.Event.trigger("key." + key);
|
Ox.Event.trigger("key_" + key);
|
||||||
/*
|
/*
|
||||||
$.each(stack, function(i, v) {
|
$.each(stack, function(i, v) {
|
||||||
// fixme: we dont get the return value!
|
// fixme: we dont get the return value!
|
||||||
|
@ -656,7 +703,6 @@ requires
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
Ox.URL
|
Ox.URL
|
||||||
|
@ -771,20 +817,35 @@ requires
|
||||||
};
|
};
|
||||||
|
|
||||||
// public
|
// 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 = function(defaults) {
|
||||||
/*
|
/*
|
||||||
that.defaults({foo: x}) sets self.defaults
|
that.defaults({foo: x}) sets self.defaults
|
||||||
*/
|
*/
|
||||||
self.defaults = defaults;
|
self.defaults = defaults;
|
||||||
return that;
|
return that;
|
||||||
}
|
};
|
||||||
that.gain = function() {
|
that.gainFocus = function() {
|
||||||
Ox.Focus.gain(that.id);
|
Ox.Focus.focus(that.id);
|
||||||
}
|
};
|
||||||
that.lose = function() {
|
that.hasFocus = function() {
|
||||||
Ox.Focus.lose(that.id);
|
return Ox.Focus.focused() == that.id;
|
||||||
}
|
};
|
||||||
that.options = function() {
|
that.loseFocus = function() {
|
||||||
|
Ox.Focus.blur(that.id);
|
||||||
|
};
|
||||||
|
that.options = function() { // fixme: use Ox.getset
|
||||||
/*
|
/*
|
||||||
that.options() returns self.options
|
that.options() returns self.options
|
||||||
that.options("foo") returns self.options.foo
|
that.options("foo") returns self.options.foo
|
||||||
|
@ -817,26 +878,21 @@ requires
|
||||||
}
|
}
|
||||||
return ret;
|
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.remove = function() {
|
||||||
that.$element.remove();
|
that.$element.remove();
|
||||||
delete elements[that.ox];
|
delete elements[that.ox];
|
||||||
}
|
}
|
||||||
that.subscribe = function() {
|
that.unbindEvent = function() {
|
||||||
Ox.Event.subscribe.apply(that, arguments);
|
/*
|
||||||
// or
|
unbindEvent(event, fn) or unbindEvent({event0: fn0, event1: fn1, ...})
|
||||||
that.$element.bind.apply(that, arguments);
|
*/
|
||||||
return that;
|
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]);
|
||||||
}
|
}
|
||||||
that.unsubscribe = function() {
|
|
||||||
Ox.Event.unsubscribe.apply(that, arguments);
|
|
||||||
return that;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return
|
// return
|
||||||
|
@ -1694,9 +1750,10 @@ requires
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0
|
top: 0
|
||||||
},
|
},
|
||||||
|
parent: null,
|
||||||
selected: -1,
|
selected: -1,
|
||||||
side: "bottom",
|
side: "bottom",
|
||||||
size: "medium"
|
size: "medium",
|
||||||
})
|
})
|
||||||
.options(options)
|
.options(options)
|
||||||
.addClass(
|
.addClass(
|
||||||
|
@ -1740,8 +1797,9 @@ requires
|
||||||
left: 0,
|
left: 0,
|
||||||
top: -4
|
top: -4
|
||||||
},
|
},
|
||||||
|
parent: that,
|
||||||
side: "right",
|
side: "right",
|
||||||
size: self.options.size
|
size: self.options.size,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1756,6 +1814,12 @@ requires
|
||||||
.addClass("OxBottom")
|
.addClass("OxBottom")
|
||||||
.appendTo(that.$element);
|
.appendTo(that.$element);
|
||||||
|
|
||||||
|
function click(event) {
|
||||||
|
if (!$(event.target).is(".OxCell")) {
|
||||||
|
that.hideMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function clickItem() {
|
function clickItem() {
|
||||||
if (self.options.selected > -1) {
|
if (self.options.selected > -1) {
|
||||||
that.items[self.options.selected].trigger("click");
|
that.items[self.options.selected].trigger("click");
|
||||||
|
@ -1823,6 +1887,7 @@ requires
|
||||||
}
|
}
|
||||||
|
|
||||||
function getElement(id) {
|
function getElement(id) {
|
||||||
|
// fixme: needed?
|
||||||
return $("#" + Ox.toCamelCase(options.id + "/" + id));
|
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() {
|
that.hideMenu = function() {
|
||||||
Ox.print("hideMenu")
|
Ox.print("hideMenu")
|
||||||
$.each(that.submenus, function(i, submenu) {
|
$.each(that.submenus, function(i, submenu) {
|
||||||
|
@ -1911,11 +2007,20 @@ requires
|
||||||
if (self.options.selected > -1) {
|
if (self.options.selected > -1) {
|
||||||
that.items[self.options.selected].trigger("mouseleave");
|
that.items[self.options.selected].trigger("mouseleave");
|
||||||
}
|
}
|
||||||
Ox.Event.unbind("key down", selectNextItem);
|
that.loseFocus();
|
||||||
Ox.Event.unbind("key up", selectPreviousItem);
|
that.unbindEvent({
|
||||||
Ox.Event.unbind("key.escape", that.hideMenu);
|
key_up: selectPreviousItem,
|
||||||
Ox.Event.unbind("key.enter", clickItem);
|
key_down: selectNextItem,
|
||||||
$document.unbind("click", that.hideMenu);
|
key_left: selectSupermenu,
|
||||||
|
key_right: selectSubmenu,
|
||||||
|
key_escape: that.hideMenu,
|
||||||
|
key_enter: clickItem
|
||||||
|
});
|
||||||
|
$document.unbind("click", click);
|
||||||
|
};
|
||||||
|
|
||||||
|
that.selectFirstItem = function() {
|
||||||
|
selectNextItem();
|
||||||
};
|
};
|
||||||
|
|
||||||
that.showMenu = function() {
|
that.showMenu = function() {
|
||||||
|
@ -1935,13 +2040,19 @@ requires
|
||||||
that.$container.height(maxHeight - itemHeight);
|
that.$container.height(maxHeight - itemHeight);
|
||||||
that.$scrollbars.down.show();
|
that.$scrollbars.down.show();
|
||||||
}
|
}
|
||||||
Ox.print("binding...");
|
if (!self.options.parent) {
|
||||||
Ox.Event.bind("key.down", selectNextItem);
|
that.gainFocus();
|
||||||
Ox.Event.bind("key.up", selectPreviousItem);
|
}
|
||||||
Ox.Event.bind("key.escape", that.hideMenu);
|
that.bindEvent({
|
||||||
Ox.Event.bind("key.enter", clickItem);
|
key_up: selectPreviousItem,
|
||||||
|
key_down: selectNextItem,
|
||||||
|
key_left: selectSupermenu,
|
||||||
|
key_right: selectSubmenu,
|
||||||
|
key_escape: that.hideMenu,
|
||||||
|
key_enter: clickItem
|
||||||
|
});
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
$document.bind("click", that.hideMenu);
|
$document.bind("click", click);
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2025,7 +2136,7 @@ requires
|
||||||
);
|
);
|
||||||
|
|
||||||
function click() {
|
function click() {
|
||||||
if (!that.hasClass("OxDisabled") && !self.options.submenu) {
|
if (!that.hasClass("OxDisabled") && !self.options.items.length) {
|
||||||
self.options.menu.hideMenu();
|
self.options.menu.hideMenu();
|
||||||
if (self.options.checked !== null && (!self.options.group || !self.options.checked)) {
|
if (self.options.checked !== null && (!self.options.group || !self.options.checked)) {
|
||||||
that.options({
|
that.options({
|
||||||
|
@ -2039,7 +2150,6 @@ requires
|
||||||
id: self.options.id,
|
id: self.options.id,
|
||||||
value: self.options.title // fixme: value or title?
|
value: self.options.title // fixme: value or title?
|
||||||
});
|
});
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2050,7 +2160,10 @@ requires
|
||||||
function mouseenter() {
|
function mouseenter() {
|
||||||
if (!self.options.disabled && !isSelected()) {
|
if (!self.options.disabled && !isSelected()) {
|
||||||
$.each(self.options.menu.submenus, function(id, submenu) {
|
$.each(self.options.menu.submenus, function(id, submenu) {
|
||||||
|
if (!submenu.is(":hidden")) {
|
||||||
submenu.hideMenu();
|
submenu.hideMenu();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (self.options.menu.options("selected") > -1) {
|
if (self.options.menu.options("selected") > -1) {
|
||||||
self.options.menu.items[self.options.menu.options("selected")].trigger("mouseleave");
|
self.options.menu.items[self.options.menu.options("selected")].trigger("mouseleave");
|
||||||
|
|
|
@ -74,14 +74,39 @@ $(function() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
title: "More",
|
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() {
|
button
|
||||||
|
.click(function() {
|
||||||
$(this).blur(); // fix for firefox
|
$(this).blur(); // fix for firefox
|
||||||
menu.toggleMenu();
|
menu.toggleMenu();
|
||||||
});
|
})
|
||||||
Ox.Event.bind("OxClickMenu", function(event, data) {
|
.bindEvent("OxClickMenu", function(event, data) {
|
||||||
button.options({
|
button.options({
|
||||||
value: data.value
|
value: data.value
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue