some more menu

This commit is contained in:
Rolux 2010-02-03 17:42:21 +05:30
parent 7a7ec9abd6
commit bef91985d6
2 changed files with 497 additions and 95 deletions

View File

@ -296,6 +296,188 @@ OxRange
margin-top: -1px; margin-top: -1px;
} }
/*
================================================================================
Menus
================================================================================
*/
.OxMenu {
position: absolute;
display: none;
z-index: 11;
-moz-border-radius-bottomleft: 4px;
-moz-border-radius-bottomright: 4px;
-moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.75);
-webkit-border-bottom-left-radius: 4px;
-webkit-border-bottom-right-radius: 4px;
-webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.75);
}
.OxMenu.OxRight {
-moz-border-radius-topright: 4px;
-webkit-border-top-right-radius: 4px;
}
.OxMenu .OxTop {
height: 4px;
background: rgba(48, 48, 48, 0.96);
}
.OxMenu.OxRight .OxTop {
-moz-border-radius-topright: 4px;
-webkit-border-top-right-radius: 4px;
}
.OxMenu .OxBottom {
height: 4px;
background: rgba(48, 48, 48, 0.96);
-moz-border-radius-bottomleft: 4px;
-moz-border-radius-bottomright: 4px;
-webkit-border-bottom-left-radius: 4px;
-webkit-border-bottom-right-radius: 4px;
}
.OxMenu .OxContainer {
background: transparent;
overflow: hidden;
}
.OxMenu .OxContent {
position: relative;
border-collapse: collapse;
border-spacing: 0;
}
.OxMenu .OxItem {
background: rgba(48, 48, 48, 0.96);
cursor: pointer;
}
.OxMenu.OxLarge .OxItem {
height: 20px;
}
.OxMenu.OxMedium .OxItem {
height: 16px;
}
.OxMenu.OxSmall .OxItem {
height: 12px;
}
.OxMenu .OxItem.OxDisabled {
cursor: default;
}
.OxMenu .OxItem.OxSelected {
background: rgba(64, 64, 64, 0.96);
}
.OxMenu.OxLarge .OxItem .OxCell {
height: 20px;
font-size: 14px;
}
.OxMenu.OxMedium .OxItem .OxCell {
height: 16px;
font-size: 11px;
}
.OxMenu.OxSmall .OxItem .OxCell {
height: 12px;
font-size: 9px;
}
.OxMenu .OxItem.OxDisabled .OxCell {
color: rgb(80, 80, 80);
}
.OxMenu .OxItem .OxCell.OxStatus {
padding-left: 4px;
text-align: right;
}
.OxMenu .OxItem .OxCell.OxIcon {
padding-left: 4px;
}
.OxMenu .OxItem .OxCell.OxIcon img {
position: relative;
top: 2px;
}
.OxMenu.OxLarge .OxItem .OxCell.OxIcon img {
width: 16px;
height: 16px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
.OxMenu.OxMedium .OxItem .OxCell.OxIcon img {
width: 12px;
height: 12px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
.OxMenu.OxSmall .OxItem .OxCell.OxIcon img {
width: 8px;
height: 8px;
-moz-border-radius: 1px;
-webkit-border-radius: 1px;
}
.OxMenu .OxItem .OxCell.OxTitle {
padding-left: 4px;
white-space: nowrap;
}
.OxMenu .OxItem .OxCell.OxModifiers {
padding-left: 4px;
text-align: right;
}
.OxMenu .OxItem .OxCell.OxKey {
padding-right: 8px;
}
.OxMenu .OxItem .OxCell.OxSubmenu {
padding-right: 8px;
text-align: right;
}
.OxMenu.OxLarge .OxItem .OxCell.OxSubmenu {
font-size: 10px;
}
.OxMenu.OxMedium .OxItem .OxCell.OxSubmenu {
font-size: 8px;
}
.OxMenu.OxSmall .OxItem .OxCell.OxSubmenu {
font-size: 6px;
}
.OxMenu.OxLarge .OxItem .OxCell.OxStatus,
.OxMenu.OxLarge .OxItem .OxCell.OxKey,
.OxMenu.OxLarge .OxItem .OxCell.OxSubmenu {
width: 12px;
}
.OxMenu.OxMedium .OxItem .OxCell.OxStatus,
.OxMenu.OxMedium .OxItem .OxCell.OxKey,
.OxMenu.OxMedium .OxItem .OxCell.OxSubmenu {
width: 10px;
}
.OxMenu.OxSmall .OxItem .OxCell.OxStatus,
.OxMenu.OxSmall .OxItem .OxCell.OxKey,
.OxMenu.OxSmall .OxItem .OxCell.OxSubmenu {
width: 8px;
}
.OxMenu .OxSpace {
height: 4px;
background: rgba(48, 48, 48, 0.96);
}
.OxMenu .OxLine {
height: 1px;
background: rgba(64, 64, 64, 0.96);
}
.OxMenu .OxScrollBar {
background: rgba(48, 48, 48, 0.96);
text-align: center;
cursor: pointer;
display: none;
}
.OxMenu.OxLarge .OxScrollBar {
height: 16px;
padding-top: 4px;
font-size: 10px;
}
.OxMenu.OxMedium .OxScrollBar {
height: 13px;
padding-top: 3px;
font-size: 8px;
}
.OxMenu.OxSmall .OxScrollBar {
height: 10px;
padding-top: 2px;
font-size: 6px;
}
.OxMenu .OxScrollBar.OxSelected {
background: rgba(64, 64, 64, 0.96);
}
/* /*
================================================================================ ================================================================================
Panels Panels

View File

@ -47,7 +47,59 @@ 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: [] stack: [], // fixme: used?
symbols: { // fixme: make lowercase
alt: "\u2325",
apple: "\uF8FF",
arrow_down: "\u2193",
arrow_left: "\u2190",
"arrow right": "\u2192",
"arrow up": "\u2191",
"backspace": "\u232B",
"backup": "\u2707",
"ballot": "\u2717",
"black star": "\u2605",
"burn": "\u2622",
"caps lock": "\u21EA",
"check": "\u2713",
"CLEAR": "\u2327",
"CLICK": "\uF803",
"CLOSE": "\u2715",
"COMMAND": "\u2318",
"CONTROL": "\u2303",
"CUT": "\u2702",
"DELETE": "\u2326",
"DIAMOND": "\u25C6",
"EDIT": "\uF802",
"EJECT": "\u23CF",
"ESCAPE": "\u238B",
"END": "\u2198",
"ENTER": "\u2324",
"FLY": "\u2708",
"GEAR": "\u2699",
"HOME": "\u2196",
"INFO": "\u24D8",
"NAVIGATE": "\u2388",
"OPTION": "\u2387",
"PAGE UP": "\u21DE",
"PAGE DOWN": "\u21DF",
"REDO": "\u21BA",
"RETURN": "\u21A9",
"SELECT": "\u21D5",
"SHIFT": "\u21E7",
"SOUND": "\u266B",
"SPACE": "\u2423",
"TAB": "\u21E5",
"TRASH": "\u267A",
"TRIANGLE DOWN": "\u25BC",
"TRIANGLE LEFT": "\u25C0",
triangle_right: "\u25BA",
"TRIANGLE UP": "\u25B2",
"UNDO": "\u21BB",
"VOLTAGE": "\u26A1",
"WARNING": "\u26A0",
"WHITE STAR": "\u2606"
}
}, },
$window, $document, $body; $window, $document, $body;
@ -130,6 +182,7 @@ requires
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
Ox.Event Ox.Event
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
naming convention for event/trigger naming convention for event/trigger
verb.id.namespace, i.e. verb.sourceId.targetId (?) verb.id.namespace, i.e. verb.sourceId.targetId (?)
... ...
@ -149,6 +202,9 @@ requires
*/ */
// use dom elements / jquery instead // use dom elements / jquery instead
$eventHandler = $("<div>");
Ox.Event = function() { Ox.Event = function() {
var events = {}; var events = {};
return { return {
@ -1145,6 +1201,7 @@ requires
that = new Ox.Element("input", self) that = new Ox.Element("input", self)
.defaults({ .defaults({
buttonId: null, buttonId: null,
click: function() {},
disabled: false, disabled: false,
groupId: null, groupId: null,
selectable: false, selectable: false,
@ -1207,6 +1264,7 @@ requires
self.options.values[1] : self.options.values[0] self.options.values[1] : self.options.values[0]
}); });
} }
self.options.click();
} }
self.onChange = function(option, value) { self.onChange = function(option, value) {
//console.log("setOption", option, value) //console.log("setOption", option, value)
@ -1262,9 +1320,9 @@ requires
.options(options || {}) .options(options || {})
.addClass("OxButtonGroup"); .addClass("OxButtonGroup");
(function() { (function() {
self.$buttons = []; that.$buttons = [];
$.each(self.options.values, function(i, v) { $.each(self.options.values, function(i, v) {
self.$buttons[i] = Ox.Button({ that.$buttons[i] = Ox.Button({
buttonId: i, buttonId: i,
groupId: self.options.groupId, groupId: self.options.groupId,
selectable: self.options.selectable, selectable: self.options.selectable,
@ -1280,7 +1338,7 @@ requires
if (data.groupId = self.options.groupId) { if (data.groupId = self.options.groupId) {
if (data.selected) { if (data.selected) {
if (self.options.selected > -1) { if (self.options.selected > -1) {
self.$buttons[self.options.selected].toggleSelected(); that.$buttons[self.options.selected].toggleSelected();
} }
self.options.selected = data.buttonId; self.options.selected = data.buttonId;
} }
@ -1581,17 +1639,17 @@ requires
side: "bottom", side: "bottom",
size: "medium" size: "medium"
}) })
.options(options), .options(options)
.addClass(
"OxMenu Ox" + Ox.toTitleCase(self.options.side) +
" 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, selected = -1,
scrollSpeed = 1, scrollSpeed = 1,
$item; $item;
// construct // construct
that.addClass(
"OxMenu Ox" + Ox.toTitleCase(options.side) +
" Ox" + Ox.toTitleCase(options.size)
);
that.$items = []; that.$items = [];
that.$scrollbars = []; that.$scrollbars = [];
that.$submenus = {}; that.$submenus = {};
@ -1606,9 +1664,12 @@ requires
that.$content = $("<table>") that.$content = $("<table>")
.addClass("OxContent") .addClass("OxContent")
.appendTo(that.$container); .appendTo(that.$container);
$.each(options.items, function(i, item) { $.each(self.options.items, function(i, item) {
$.extend(item, {
menu: that
});
if (item.id) { if (item.id) {
$item = constructItem(item) $item = new Ox.MenuItem(item)
.data("pos", i) .data("pos", i)
.appendTo(that.$content); .appendTo(that.$content);
that.$items.push($item); that.$items.push($item);
@ -1624,46 +1685,96 @@ requires
that.$bottom = $("<div>") that.$bottom = $("<div>")
.addClass("OxBottom") .addClass("OxBottom")
.appendTo(that.$element); .appendTo(that.$element);
$.each(options.items, function(i, item) {
if (item.items.length) {
that.$submenus[item.id] = new Ox.Menu({
id: options.id + "/" + item.id,
side: "right",
offset: {
left: 0,
top: -4
},
size: args.size,
items: item.items
});
}
});
function constructItem(item) {
}
function constructLine() { function constructLine() {
return $("<tr>").append(
$("<td>").addClass("OxLine", {
attr: {
colspan: 5
}
})
);
} }
function constructScrollbar(direction) { function constructScrollbar(direction) {
var interval;
return $("<div/>", {
addClass: "OxScrollBar Ox" + Ox.toTitleCase(direction),
html: oxui.symbols["triangle_" + direction],
click: function() { // fixme: do we need to listen to click event?
return false;
},
mousedown: function() {
scrollSpeed = 2;
return false;
},
mouseenter: function() {
var $otherScrollbar = that.$scrollbars[direction == "up" ? "down" : "up"];
$(this).addClass("OxSelected");
if ($otherScrollbar.is(":hidden")) {
$otherScrollbar.show();
that.$container.height(that.$container.height() - itemHeight);
if (direction == "down") {
that.$content.css({
top: -itemHeight + "px"
});
}
}
scrollMenu(direction == "up" ? -1 : 1);
interval = setInterval(function() {
scrollMenu(direction == "up" ? -1 : 1);
}, 100);
},
mouseleave: function() {
$(this).removeClass("OxSelected");
clearInterval(interval);
},
mouseup: function() {
scrollSpeed = 1;
return false;
}
});
} }
function constructSpace() { function constructSpace() {
return $("<tr>").append(
$("<td>").addClass("OxSpace", {
attr: {
colspan: 5
}
})
);
} }
function getElement(id) { function getElement(id) {
return $("#" + Ox.toCamelCase(options.id + "/" + id)); return $("#" + Ox.toCamelCase(options.id + "/" + id));
} }
function parseShortcut() { function scrollMenu(speed) {
var containerHeight = that.$container.height(),
contentHeight = that.$content.height(),
top = parseInt(that.$content.css("top")) || 0,
min = containerHeight - contentHeight + itemHeight,
max = 0;
top += speed * scrollSpeed * -itemHeight;
if (top <= min) {
top = min;
that.$scrollbars.down.hide().trigger("mouseleave");
that.$container.css({
height: (containerHeight + itemHeight) + "px"
});
that.$items[that.$items.length - 1].trigger("mouseover");
} else if (top >= max - itemHeight) {
top = max;
that.$scrollbars.up.hide().trigger("mouseleave");
that.$container.css({
height: (containerHeight + itemHeight) + "px"
});
that.$items[0].trigger("mouseover");
} }
that.$content.css({
function scroll(speed) { top: top + "px"
});
} }
@ -1675,62 +1786,53 @@ requires
} }
that.check = function(id) {
};
that.disable = function(id) {
};
that.enable = function(id) {
};
that.hideMenu = function() { that.hideMenu = function() {
$.each(that.$submenus, function(i, $submenu) {
}; if (!$submenu.is(":hidden")) {
$submenu.hideMenu();
that.insertItemAfter = function(id, item) { return false;
}
}; });
// fixme: scroll menu back up!
that.insertItemBefore = function(id, item) { that.hide();
};
that.removeItem = function(id) {
}; };
that.showMenu = function() { that.showMenu = function() {
Ox.print("showMenu")
var offset = that.$element.offset(),
padding = {
left: parseInt(that.$element.css("padding-left")),
top: parseInt(that.$element.css("padding-top")),
},
width = that.$element.width(),
height = that.$element.height(),
left = offset.left + self.options.offset.left + (self.options.side == "bottom" ? 0 : width + padding.left),
top = offset.top + self.options.offset.top + (self.options.side == "bottom" ? height + padding.top : 0),
maxHeight = Math.floor(($window.height() - top - 12) / itemHeight) * itemHeight;
that.css({
left: left + "px",
top: top + "px"
}).show();
that.parent().length || that.appendTo($body);
if (height > maxHeight) {
that.$container.height(maxHeight - itemHeight);
that.$scrollbars.down.show();
}
}; };
that.toggleChecked = function(id) { that.toggleMenu = function() {
Ox.print("toggleMenu")
}; that.is(":hidden") ? that.showMenu() : that.hideMenu();
that.toggleDisabled = function(id) {
};
that.toggleTitle = function(id) {
};
that.uncheck = function(id) {
}; };
return that; return that;
} };
Ox.MenuItem = function(options, self) { Ox.MenuItem = function(options, self) {
var self = self || {}, var self = self || {},
that = new Ox.Element("tr") that = new Ox.Element("tr", self)
.defaults({ .defaults({
bind: [], bind: [],
checked: false, checked: false,
@ -1739,28 +1841,146 @@ requires
group: "", group: "",
icon: "", icon: "",
id: "", id: "",
items: [], keyboard: "",
menu: "", menu: null, // fixme: is passing the menu to 100s of menu items really memory-neutral?
shortcut: { submenu: null,
modifiers: [], title: [],
key: ""
},
title: "",
}) })
.options(options); .options($.extend(options, {
keyboard: parseKeyboard(options.keyboard || self.defaults.keyboard),
that.addClass("OxItem " + (options.disabled ? "OxDisabled" : "")) title: Ox.makeArray(options.title || self.defaults.title)
}))
.addClass("OxMenuItem " + (self.options.disabled ? "OxDisabled" : ""))
.attr({ .attr({
id: Ox.toCamelCase(options.menu + "/" + options.id) id: Ox.toCamelCase(self.options.menu + "/" + self.options.id)
}) })
.data("group", options.group) .click(click)
.mouseenter() .data("group", self.options.group)
.mouseleave() .mouseenter(mouseenter)
.click(); .mouseleave(mouseleave);
// construct
that.append(
that.$status = $("<td>", {
addClass: "OxCell OxStatus",
html: self.options.checked ? oxui.symbols.check : ""
})
)
.append(
that.$icon = $("<td>", {
"addClass": "OxCell OxIcon"
})
.append(self.options.icon ?
$("<img>", {
attr: {
src: self.options.icon
}
}) : null
)
)
.append(
that.$title = $("<td>", {
addClass: "OxCell OxTitle",
html: self.options.title[0]
})
)
.append(
$("<td>", {
addClass: "OxCell OxModifiers",
html: $.map(self.options.keyboard.modifiers, function(modifier) {
return oxui.symbol[modifier];
}).join("")
})
)
.append(
$("<td>", {
addClass: "OxCell Ox" + (self.options.submenu ? "Submenu" : "Key"),
html: self.options.submenu ? oxui.symbols.triangle_right :
oxui.symbols[self.options.keyboard.key] || self.options.keyboard.key
})
)
function click() {
if (!that.hasClass("OxDisabled") && !self.options.submenu) {
menu.hideMenu();
self.options.click();
if (self.options.group && !self.options.checked) {
that.options({
checked: true
})
}
if (self.options.title.length == 2) {
that.toggleTitle();
}
$eventHandler.trigger("clickMenu", self.options.id);
return false;
}
}
function mouseenter() {
if (!that.is(".OxDisabled") && !that.is(".OxSelected")) {
$.each(self.options.menu.submenus, function(id, submenu) {
submenu.hideMenu();
});
$(".OxMenu .OxMenuItem[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");
}
}
function mouseleave() {
if (!that.hasClass("OxDisabled") && !self.options.submenu) {
that.removeClass("OxSelected");
}
}
function parseKeyboard(str) {
var modifiers = str.split(' '),
key = modifiers.pop();
return {
modifiers: modifiers,
key: key
}
}
self.onChange = function(key, value) {
if (key == "checked") {
that.$status.html(oxui.symbols.checked);
} else if (key == "disabled") {
that.toggleClass("disabled"); // fixme: this will only work if onChange is only invoked on actual change
}
}
that.insertItemAfter = function(item) {
};
that.insertItemBefore = function(item) {
};
that.removeItem = function() {
};
that.toggleChecked = function() {
};
that.toggleDisabled = function() {
};
that.toggleTitle = function() {
that.options({
title: that.$title.html() == self.options.title[0] ?
self.options.title[1] : self.options.title[0]
})
};
return that; return that;
} };
/* /*
============================================================================ ============================================================================