4792 lines
No EOL
165 KiB
JavaScript
4792 lines
No EOL
165 KiB
JavaScript
/*
|
|
################################################################################
|
|
ox.ui.js
|
|
|
|
requires
|
|
jquery-1.4.js
|
|
ox.js
|
|
################################################################################
|
|
*/
|
|
|
|
// also see test.js, in demos ...
|
|
|
|
(function() {
|
|
|
|
var oxui = {
|
|
defaultTheme: "classic",
|
|
elements: {},
|
|
getDimensions: function(orientation) {
|
|
return orientation == "horizontal" ?
|
|
["width", "height"] : ["height", "width"];
|
|
},
|
|
getEdges: function(orientation) {
|
|
return orientation == "horizontal" ?
|
|
["left", "right", "top", "bottom"] :
|
|
["top", "bottom", "left", "right"];
|
|
},
|
|
getBarSize: function(size) {
|
|
var sizes = {
|
|
small: 20,
|
|
medium: 24,
|
|
large: 28,
|
|
};
|
|
return sizes[size];
|
|
},
|
|
jQueryFunctions: function() {
|
|
var functions = [],
|
|
$element = $("<div>");
|
|
//delete $element.length;
|
|
Ox.each($element, function(k, v) {
|
|
if (typeof v == "function") {
|
|
functions.push(k);
|
|
}
|
|
});
|
|
return functions.sort();
|
|
}(),
|
|
path: $("script[src*=ox.ui.js]").attr("src")
|
|
.replace("js/ox.ui.js", ""),
|
|
scrollbarSize: $.browser.mozilla ? 16 : 12,
|
|
symbols: {
|
|
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",
|
|
clear: "\u00D7",
|
|
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",
|
|
select: "\u25BE",
|
|
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;
|
|
|
|
$(function() {
|
|
$window = $(window),
|
|
$document = $(document),
|
|
$body = $("body"),
|
|
$elements = {};
|
|
Ox.theme(oxui.defaultTheme);
|
|
});
|
|
|
|
/*
|
|
============================================================================
|
|
Application
|
|
============================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.App
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.App = function() {
|
|
/*
|
|
options:
|
|
requestTimeout
|
|
requestType
|
|
requestURL
|
|
*/
|
|
return function(options) {
|
|
|
|
options = options || {};
|
|
var self = {},
|
|
that = this;
|
|
|
|
self.options = $.extend({
|
|
requestTimeout: oxui.requestTimeout,
|
|
requestType: oxui.requestType,
|
|
requestURL: oxui.requestURL
|
|
}, options);
|
|
|
|
self.change = function(key, value) {
|
|
|
|
};
|
|
|
|
that.launch = function() {
|
|
$.ajaxSetup({
|
|
timeout: self.options.requestTimeout,
|
|
type: self.options.requestType,
|
|
url: self.options.requestURL
|
|
});
|
|
};
|
|
|
|
that.options = function() {
|
|
return Ox.getset(self.options, Array.slice.call(arguments), self.change, that);
|
|
};
|
|
|
|
that.request = function(action, data, callback) {
|
|
if (arguments.length == 2) {
|
|
callback = data;
|
|
data = {};
|
|
}
|
|
return Ox.Request.send({
|
|
url: self.options.requestURL,
|
|
data: {
|
|
action: action,
|
|
data: JSON.stringify(data)
|
|
},
|
|
callback: callback
|
|
});
|
|
};
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
}();
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Event
|
|
----------------------------------------------------------------------------
|
|
|
|
naming convention for event/trigger
|
|
verb.id.namespace, i.e. verb.sourceId.targetId (?)
|
|
...
|
|
bind("keydown.shift+dot.numpad", function() {
|
|
// ...
|
|
})
|
|
keyboard handler then would:
|
|
$.each(stack, function(i, v) {
|
|
elements[v].trigger("keydown.shift+0.numpad");
|
|
});
|
|
and the element would implement
|
|
this.trigger(event, data) {
|
|
|
|
}
|
|
...
|
|
keyboard handler also triggers keydown.buffer
|
|
*/
|
|
|
|
// use dom elements / jquery instead
|
|
|
|
Ox.Event = function() {
|
|
var keyboardEvents = {};
|
|
$eventHandler = $("<div>");
|
|
function isKeyboardEvent(event) {
|
|
return event.substr(0, 4) == "key_";
|
|
}
|
|
return {
|
|
bind: function(id, event, callback) {
|
|
if (arguments.length == 2) {
|
|
callback = event;
|
|
event = id;
|
|
}
|
|
if (isKeyboardEvent(event)) {
|
|
keyboardEvents[id] = keyboardEvents[id] || {};
|
|
keyboardEvents[id][event] = callback;
|
|
}
|
|
if (!isKeyboardEvent(event) || Ox.Focus.focused() == id) {
|
|
Ox.print("bind", id, event)
|
|
$eventHandler.bind(event, callback);
|
|
}
|
|
},
|
|
bindKeyboard: function(id) {
|
|
$.each(keyboardEvents[id] || [], function(event, callback) {
|
|
Ox.Event.bind(id, event, callback);
|
|
//$eventHandler.bind(event, callback);
|
|
});
|
|
},
|
|
trigger: function(event, data) {
|
|
Ox.print("trigger", event, data || {});
|
|
$eventHandler.trigger(event, data || {});
|
|
},
|
|
unbind: function(id, event, callback) {
|
|
if (isKeyboardEvent(event)) {
|
|
$.each(keyboardEvents[id] || [], function(e, callback) {
|
|
if (e == event) {
|
|
delete keyboardEvents[id][e];
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
Ox.print("unbind", id, event)
|
|
$eventHandler.unbind(event, callback);
|
|
},
|
|
unbindKeyboard: function(id) {
|
|
$.each(keyboardEvents[id] || [], function(event, callback) {
|
|
Ox.print("unbind", id, event)
|
|
$eventHandler.unbind(event, callback);
|
|
});
|
|
}
|
|
}
|
|
}();
|
|
|
|
Ox.Event_ = function() { // unused
|
|
var events = {};
|
|
return {
|
|
// make these bind, trigger, unbind
|
|
publish: function(event, data) {
|
|
if (events[event]) {
|
|
$.each(events[event], function(i, v) {
|
|
setTimeout(function() {
|
|
v(data);
|
|
}, 0);
|
|
});
|
|
}
|
|
},
|
|
subscribe: function(event, callback) {
|
|
if (events[event]) {
|
|
events[event].push(callback);
|
|
} else {
|
|
events[event] = [callback];
|
|
}
|
|
},
|
|
unsubscribe: function(event, callback) {
|
|
$.each(events[event], function(i, v) {
|
|
if (Ox.startsWith(callback.toString(), v.toString())) {
|
|
events[event].splice(i, 1);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}();
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Focus
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Focus = function() {
|
|
var stack = [];
|
|
return {
|
|
blur: function(id) {
|
|
if (stack.indexOf(id) == stack.length - 1) {
|
|
$elements[Ox.Focus.focused()].removeClass("OxFocus");
|
|
$(".OxFocus").removeClass("OxFocus"); // fixme: the above is better, and should work
|
|
stack.splice(stack.length - 2, 0, stack.pop());
|
|
Ox.Event.unbindKeyboard(id);
|
|
Ox.Event.bindKeyboard(stack[stack.length - 1]);
|
|
Ox.print("blur", id, stack);
|
|
}
|
|
},
|
|
focus: function(id) {
|
|
var index = stack.indexOf(id);
|
|
if (stack.length) {
|
|
Ox.Event.unbindKeyboard(stack[stack.length - 1])
|
|
}
|
|
if (index > -1) {
|
|
stack.splice(index, 1);
|
|
}
|
|
stack.push(id);
|
|
$elements[Ox.Focus.focused()].addClass("OxFocus");
|
|
Ox.Event.bindKeyboard(id);
|
|
Ox.print("focus", id, stack);
|
|
},
|
|
focused: function() {
|
|
return stack[stack.length - 1];
|
|
}
|
|
};
|
|
}();
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.History
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Keyboard
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
(function() {
|
|
|
|
var buffer = "",
|
|
bufferTime = 0,
|
|
bufferTimeout = 1000,
|
|
keyNames = function() {
|
|
return {
|
|
0: "section",
|
|
8: "backspace",
|
|
9: "tab",
|
|
12: "clear",
|
|
13: "enter",
|
|
16: "shift",
|
|
17: "control",
|
|
18: "alt",
|
|
20: "capslock",
|
|
27: "escape",
|
|
32: "space",
|
|
33: "pageup",
|
|
34: "pagedown",
|
|
35: "end",
|
|
36: "home",
|
|
37: "left",
|
|
38: "up",
|
|
39: "right",
|
|
40: "down",
|
|
45: "insert",
|
|
46: "delete",
|
|
47: "help",
|
|
48: "0",
|
|
49: "1",
|
|
50: "2",
|
|
51: "3",
|
|
52: "4",
|
|
53: "5",
|
|
54: "6",
|
|
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",
|
|
91: "meta.left",
|
|
92: "meta.right",
|
|
93: "select",
|
|
96: "0.numpad",
|
|
97: "1.numpad",
|
|
98: "2.numpad",
|
|
99: "3.numpad",
|
|
100: "4.numpad",
|
|
101: "5.numpad",
|
|
102: "6.numpad",
|
|
103: "7.numpad",
|
|
104: "8.numpad",
|
|
105: "9.numpad",
|
|
106: "asterisk.numpad",
|
|
107: "plus.numpad",
|
|
109: "minus.numpad",
|
|
108: "enter.numpad",
|
|
110: "dot.numpad",
|
|
111: "slash.numpad",
|
|
112: "f1",
|
|
113: "f2",
|
|
114: "f3",
|
|
115: "f4",
|
|
116: "f5",
|
|
117: "f6",
|
|
118: "f7",
|
|
119: "f8",
|
|
120: "f9",
|
|
121: "f10",
|
|
122: "f11",
|
|
123: "f12",
|
|
124: "f13",
|
|
125: "f14",
|
|
126: "f15",
|
|
127: "f16",
|
|
144: "numlock",
|
|
145: "scrolllock",
|
|
186: "semicolon",
|
|
187: "equal",
|
|
188: "comma",
|
|
189: "minus",
|
|
190: "dot",
|
|
191: "slash",
|
|
192: "backtick",
|
|
219: "openbracket",
|
|
220: "backslash",
|
|
221: "closebracket",
|
|
222: "quote"
|
|
// see dojo, for ex.
|
|
};
|
|
}(),
|
|
modifierNames = {
|
|
altKey: "alt", // mac: option
|
|
ctrlKey: "control",
|
|
// metaKey: "meta", // mac: command
|
|
shiftKey: "shift"
|
|
};
|
|
|
|
$(function() {
|
|
// fixme: how to do this better?
|
|
// in firefox on mac, keypress doesn't fire for up/down
|
|
// if the cursor is at the start/end of an input element
|
|
// on linux, it doesn't seem to fire if the input element has focus
|
|
if ($.browser.mozilla) {
|
|
$document.keypress(keypress);
|
|
$document.keydown(function(event) {
|
|
var $element = $("input:focus");
|
|
if ($element.length) {
|
|
if (
|
|
(
|
|
keyNames[event.keyCode] == "up" &&
|
|
$element[0].selectionStart + $element[0].selectionEnd == 0
|
|
) || (
|
|
keyNames[event.keyCode] == "down" &&
|
|
$element[0].selectionStart == $element.val().length &&
|
|
$element[0].selectionEnd == $element.val().length
|
|
)
|
|
) {
|
|
keypress(event);
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
$document.keydown(keypress);
|
|
}
|
|
});
|
|
function keypress(event) {
|
|
var key,
|
|
keys = [],
|
|
//ret = true,
|
|
time;
|
|
$.each(modifierNames, function(k, v) {
|
|
if (event[k]) {
|
|
keys.push(v);
|
|
}
|
|
});
|
|
// avoid pushing modifier twice
|
|
Ox.print("keys", keys)
|
|
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);
|
|
//return false;
|
|
/*
|
|
$.each(stack, function(i, v) {
|
|
// fixme: we dont get the return value!
|
|
ret = Ox.event.trigger(keyboard + Ox.toCamelCase(key) + "." + v);
|
|
return ret;
|
|
});
|
|
*/
|
|
}
|
|
|
|
})();
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Mouse (??)
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Request
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Request = function() {
|
|
|
|
var cache = {},
|
|
pending = {},
|
|
requests = {},
|
|
self = {
|
|
options: {
|
|
timeout: 15000,
|
|
type: "POST",
|
|
url: "api"
|
|
}
|
|
};
|
|
|
|
return {
|
|
|
|
cancel: function() {
|
|
var index;
|
|
if (arguments.length == 0) {
|
|
requests = {};
|
|
} else if (Ox.isFunction(arguments[0])) {
|
|
// cancel with function
|
|
$.each(requests, function(id, req) {
|
|
if (arguments[0](req)) {
|
|
delete requests[id];
|
|
}
|
|
})
|
|
} else {
|
|
// cancel by id
|
|
delete requests[arguments[0]]
|
|
}
|
|
},
|
|
|
|
emptyCache: function() {
|
|
cache = {};
|
|
},
|
|
|
|
options: function(options) {
|
|
return Ox.getset(self.options, options, $.noop(), this);
|
|
},
|
|
|
|
send: function(options) {
|
|
|
|
var options = $.extend({
|
|
age: -1,
|
|
callback: function() {},
|
|
id: Ox.uid(),
|
|
timeout: self.options.timeout,
|
|
type: self.options.type,
|
|
url: self.options.url
|
|
}, options),
|
|
req = JSON.stringify({
|
|
url: options.url,
|
|
data: options.data
|
|
});
|
|
|
|
function callback(data) {
|
|
delete requests[options.id];
|
|
Ox.length(requests) == 0 && Ox.Event.trigger("requestStop");
|
|
options.callback(data);
|
|
}
|
|
|
|
function debug(request) {
|
|
var $iframe = $("<iframe>")
|
|
.css({ // fixme: should go into a class
|
|
width: 768,
|
|
height: 384
|
|
}),
|
|
$dialog = new Ox.Dialog({
|
|
title: "Application Error",
|
|
buttons: [
|
|
{
|
|
value: "Close",
|
|
click: function() {
|
|
$dialog.close();
|
|
}
|
|
}
|
|
],
|
|
width: 800,
|
|
height: 400
|
|
})
|
|
.append($iframe)
|
|
.open(),
|
|
iframe = $iframe[0].contentDocument || $iframe[0].contentWindow.document;
|
|
iframe.open();
|
|
iframe.write(request.responseText);
|
|
iframe.close();
|
|
}
|
|
|
|
function error(request, status, error) {
|
|
var data;
|
|
if (arguments.length == 1) {
|
|
data = arguments[0]
|
|
} else {
|
|
try {
|
|
data = JSON.parse(request.responseText);
|
|
} catch (err) {
|
|
data = {
|
|
status: {
|
|
code: request.status,
|
|
text: request.statusText
|
|
}
|
|
};
|
|
}
|
|
}
|
|
if (data.status.code < 500) {
|
|
callback(data);
|
|
} else {
|
|
var $dialog = new Ox.Dialog({
|
|
title: "Application Error",
|
|
buttons: [
|
|
{
|
|
value: "Details",
|
|
click: function() {
|
|
$dialog.close(function() {
|
|
debug(request);
|
|
});
|
|
}
|
|
},
|
|
{
|
|
value: "Close",
|
|
click: function() {
|
|
$dialog.close(function() {
|
|
callback(data);
|
|
});
|
|
}
|
|
}
|
|
],
|
|
width: 400,
|
|
height: 200
|
|
})
|
|
.append("Sorry, we have encountered an application error while handling your request. To help us find out what went wrong, you may want to report this error to an administrator. Otherwise, please try again later.")
|
|
.open();
|
|
// fixme: change this to Send / Don't Send
|
|
Ox.print({
|
|
request: request,
|
|
status: status,
|
|
error: error
|
|
});
|
|
}
|
|
pending[options.id] = false;
|
|
}
|
|
|
|
function success(data) {
|
|
pending[options.id] = false;
|
|
cache[req] = {
|
|
data: data,
|
|
time: Ox.getTime()
|
|
};
|
|
callback(data);
|
|
}
|
|
|
|
if (pending[options.id]) {
|
|
setTimeout(function() {
|
|
Ox.Request.send(options);
|
|
}, 0);
|
|
} else {
|
|
requests[options.id] = {
|
|
url: options.url,
|
|
data: options.data
|
|
};
|
|
if (cache[req] && (options.age == -1 || options.age > Ox.getTime() - cache[req].time)) {
|
|
setTimeout(function() {
|
|
callback(cache[req].data);
|
|
}, 0);
|
|
} else {
|
|
pending[options.id] = true;
|
|
$.ajax({
|
|
data: options.data,
|
|
dataType: "json",
|
|
error: error,
|
|
success: success,
|
|
timeout: options.timeout,
|
|
type: options.type,
|
|
url: options.url
|
|
});
|
|
Ox.print("request", options.data);
|
|
Ox.length(requests) == 1 && Ox.Event.trigger("requestStart");
|
|
}
|
|
}
|
|
|
|
return options.id;
|
|
|
|
},
|
|
|
|
requests: function() {
|
|
return Ox.length(requests);
|
|
}
|
|
|
|
};
|
|
}();
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.URL
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
============================================================================
|
|
Core
|
|
============================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Container
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
// fixme: wouldn't it be better to let the elements be,
|
|
// rather then $element, $content, and potentially others,
|
|
// 0, 1, 2, etc, so that append would append 0, and appendTo
|
|
// would append (length - 1)?
|
|
Ox.Container = function(options, self) {
|
|
var that = new Ox.Element(options, self)
|
|
.addClass("OxContainer");
|
|
that.$content = new Ox.Element(options, self)
|
|
.addClass("OxContent")
|
|
.appendTo(that);
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Element
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
// check out http://ejohn.org/apps/learn/#36 (-#38, making fns work w/o new)
|
|
|
|
Ox.Element = function() {
|
|
|
|
var elements = {}; // fixme: unused, we need this outside Element (for Focus)
|
|
|
|
return function(options, self) {
|
|
|
|
// construct
|
|
options = options || {};
|
|
self = self || {};
|
|
var that = this;
|
|
|
|
// init
|
|
(function() {
|
|
// allow for Ox.Widget("tagname", self)
|
|
if (typeof options == "string") {
|
|
options = {
|
|
element: options
|
|
};
|
|
}
|
|
that.ox = Ox.version;
|
|
that.id = Ox.uid();
|
|
that.$element = $("<" + (options.element || "div") + "/>", {
|
|
data: {
|
|
ox: that.id
|
|
}
|
|
});
|
|
$elements[that.id] = that;
|
|
wrapjQuery();
|
|
})();
|
|
|
|
// private
|
|
function wrapjQuery() {
|
|
$.each(oxui.jQueryFunctions, function(i, fn) {
|
|
that[fn] = function() {
|
|
var args = arguments,
|
|
length = args.length,
|
|
id, ret;
|
|
$.each(args, function(i, arg) {
|
|
// if an ox object was passed
|
|
// then pass its $element instead
|
|
// so we can do oxObj.jqFn(oxObj)
|
|
if (arg.ox) {
|
|
args[i] = arg.$element;
|
|
}
|
|
/*
|
|
if (arg.ox) { // fixme: or is this too much magic?
|
|
if (fn == "appendTo" && arg.$content) {
|
|
args[i] = arg.$content
|
|
} else {
|
|
args[i] = arg.$element;
|
|
}
|
|
}
|
|
*/
|
|
});
|
|
/*
|
|
if (fn == "html" && that.$content) { // fixme: or is this too much magic?
|
|
$element = that.$content;
|
|
} else {
|
|
$element = that.$element;
|
|
}
|
|
*/
|
|
// why does this not work?
|
|
// ret = that.$element[v].apply(this, arguments);
|
|
if (length == 0) {
|
|
ret = that.$element[fn]();
|
|
} else if (length == 1) {
|
|
ret = that.$element[fn](args[0]);
|
|
} else if (length == 2) {
|
|
ret = that.$element[fn](args[0], args[1]);
|
|
} else if (length == 3) {
|
|
ret = that.$element[fn](args[0], args[1], args[2]);
|
|
} else if (length == 4) {
|
|
ret = that.$element[fn](args[0], args[1], args[2], args[3]);
|
|
}
|
|
if (fn == "data") {
|
|
// Ox.print("data ret", ret, $(ret))
|
|
}
|
|
// if the $element of an ox object was returned
|
|
// then return the ox object instead
|
|
// so we can do oxObj.jqFn().oxFn()
|
|
return ret.jquery && $elements[id = ret.data("ox")] ?
|
|
$elements[id] : ret;
|
|
}
|
|
});
|
|
}
|
|
|
|
// shared
|
|
self.onChange = function() {
|
|
// self.onChange(key, value)
|
|
// is called when an option changes
|
|
// (to be implemented by widget)
|
|
};
|
|
|
|
// public
|
|
that.bindEvent = function() {
|
|
// fixme: shouldn't this work the other way around,
|
|
// and bind a function to an event triggered by this widget?
|
|
/*
|
|
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]);
|
|
}
|
|
return that;
|
|
};
|
|
that.defaults = function(defaults) {
|
|
/*
|
|
that.defaults({foo: x}) sets self.defaults
|
|
*/
|
|
self.defaults = defaults;
|
|
delete self.options; // fixme: hackish fix for that = Ox.Foo({...}, self).defaults({...}).options({...})
|
|
return that;
|
|
};
|
|
that.gainFocus = function() {
|
|
Ox.Focus.focus(that.id);
|
|
return that;
|
|
};
|
|
that.hasFocus = function() {
|
|
return Ox.Focus.focused() == that.id;
|
|
};
|
|
that.loseFocus = function() {
|
|
Ox.Focus.blur(that.id);
|
|
return that;
|
|
};
|
|
that.options = function() { // fixme: use Ox.getset
|
|
/*
|
|
that.options() returns self.options
|
|
that.options("foo") returns self.options.foo
|
|
that.options("foo", x) sets self.options.foo,
|
|
returns that
|
|
that.options({foo: x, bar: y}) sets self.options.foo
|
|
and self.options.bar,
|
|
returns that
|
|
*/
|
|
var length = arguments.length,
|
|
// args, options, ret;
|
|
args, ret;
|
|
if (length == 0) {
|
|
// options()
|
|
ret = self.options || options; // this is silly. make sure self.options get populated with options
|
|
} else if (length == 1 && typeof arguments[0] == "string") {
|
|
// options(str)
|
|
ret = self.options ? self.options[arguments[0]] : options[arguments[0]];
|
|
} else {
|
|
// options (str, val) or options({str: val, ...})
|
|
// translate (str, val) to ({str: val})
|
|
args = Ox.makeObject.apply(that, arguments);
|
|
/*
|
|
options = self.options;
|
|
*/
|
|
// if options have not been set, extend defaults,
|
|
// otherwise, extend options
|
|
self.options = $.extend(self.options || self.defaults, args);
|
|
$.each(args, function(key, value) {
|
|
self.onChange(key, value);
|
|
/*
|
|
fixme: why does this not work?
|
|
Ox.print("options", options, key, value)
|
|
//Ox.print(!options, !options || !options[key], !options || !options[key] || options[key] !== value)
|
|
if (!options || !options[key] || options[key] !== value) {
|
|
Ox.print("onChange...")
|
|
self.onChange(key, value);
|
|
} else {
|
|
Ox.print("NO CHANGE");
|
|
}
|
|
*/
|
|
});
|
|
ret = that;
|
|
}
|
|
return ret;
|
|
};
|
|
that.remove = function() {
|
|
that.$element.remove();
|
|
delete $elements[that.ox];
|
|
return that;
|
|
};
|
|
that.triggerEvent = function() {
|
|
/*
|
|
triggerEvent(event, fn) or triggerEvent({event0: fn0, event1: fn1, ...})
|
|
*/
|
|
if (Ox.isObject(arguments[0])) {
|
|
$.each(arguments[0], function(event, fn) {
|
|
Ox.Event.trigger(event + "_" + self.options.id, fn);
|
|
});
|
|
} else {
|
|
Ox.Event.trigger(arguments[0] + "_" + self.options.id, arguments[1] || {});
|
|
}
|
|
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 that;
|
|
};
|
|
|
|
// return
|
|
return that;
|
|
|
|
}
|
|
|
|
}();
|
|
|
|
Ox._Element = function(element) {
|
|
var that = this;
|
|
that.def = {};
|
|
that.opt = {};
|
|
that.ox = Ox.version;
|
|
that.id = Ox.uid();
|
|
//Ox.print("that.id", that.id)
|
|
that.$element = $("<" + (element || "div") + "/>")
|
|
//.addClass("OxElement")
|
|
.data("ox", that.id);
|
|
oxui.elements[that.id] = that;
|
|
// Ox.print("oxui.elements", oxui.elements)
|
|
//function setOption() {};
|
|
that.setOption = function() {};
|
|
/*
|
|
*/
|
|
that.destroy = function() {
|
|
that.$element.remove();
|
|
delete oxui.elements[that.ox];
|
|
}
|
|
/*
|
|
*/
|
|
that.disable = function() {
|
|
|
|
}
|
|
/*
|
|
*/
|
|
that.enable = function() {
|
|
|
|
}
|
|
/*
|
|
*/
|
|
///*
|
|
that.defaults = function() {
|
|
var length = arguments.length,
|
|
ret;
|
|
if (length == 0) {
|
|
ret = that.def
|
|
} else if (length == 1 && typeof arguments[0] == "string") {
|
|
ret = that.def[arguments[0]];
|
|
} else {
|
|
// translate ("key", "value") to {"key": "value"}
|
|
that.def = $.extend(
|
|
that.def, Ox.makeObject.apply(that, arguments)
|
|
);
|
|
ret = that;
|
|
}
|
|
return ret;
|
|
}
|
|
//*/
|
|
/*
|
|
Ox.Element.options()
|
|
get options
|
|
Ox.Element.options("foo")
|
|
get options.foo
|
|
Ox.Element.options("foo", 0)
|
|
set options.foo
|
|
Ox.Element.options({foo: 0, bar: 1})
|
|
set options.foo and options.bar
|
|
*/
|
|
///*
|
|
that.options = function() {
|
|
var length = arguments.length,
|
|
args, ret;
|
|
if (length == 0) {
|
|
//Ox.print("getting all options", options);
|
|
ret = that.opt;
|
|
} else if (length == 1 && typeof arguments[0] == "string") {
|
|
//Ox.print("getting one option", options, arguments[0], options[arguments[0]]);
|
|
ret = that.opt[arguments[0]];
|
|
} else {
|
|
// translate ("key", "value") to {"key": "value"}
|
|
args = Ox.makeObject.apply(that, arguments);
|
|
// if options have been set then extend options,
|
|
// otherwise extend defaults
|
|
that.opt = $.extend(Ox.length(that.opt) ?
|
|
that.opt : that.def, args);
|
|
// that.trigger("OxElement" + that.id + "SetOptions", args);
|
|
$.each(args, function(k, v) {
|
|
that.setOption(k, v);
|
|
//Ox.print("triggering", "OxElement" + that.id + "SetOption", {k: v})
|
|
//that.trigger("OxElement" + that.id + "SetOption", {k: v});
|
|
})
|
|
ret = that;
|
|
}
|
|
return ret;
|
|
}
|
|
// should become self.publish
|
|
that.publish = function(event, data) {
|
|
Ox.Event.publish(event + that.id, data);
|
|
return that;
|
|
}
|
|
that.subscribe = function(event, callback) {
|
|
Ox.Event.subscribe(event, callback);
|
|
return that;
|
|
}
|
|
//that.setOptions = function() {};
|
|
//*/
|
|
// wrap jquery functions
|
|
// so we can do oxObj.jqFn()
|
|
$.each(oxui.jqueryFunctions, function(i, v) {
|
|
that[v] = function() {
|
|
var args = arguments,
|
|
length = args.length,
|
|
$element, id, ret;
|
|
$.each(args, function(i, v) {
|
|
// if an oxui object was passed
|
|
// then pass its $element instead
|
|
// so we can do jqObj.append(oxObj)
|
|
if (v.ox) {
|
|
args[i] = v.$element;
|
|
}
|
|
});
|
|
if (v == "html" && that.$content) {
|
|
$element = that.$content;
|
|
} else {
|
|
$element = that.$element;
|
|
}
|
|
// why does this not work?
|
|
// ret = that.$element[v].apply(this, arguments);
|
|
// maybe because we pass this, and not that.$element[v] ... ?
|
|
// ret = that.$element[v].apply(that.$element[v], arguments);
|
|
// doesn't work either ...
|
|
if (length == 0) {
|
|
ret = $element[v]();
|
|
} else if (length == 1) {
|
|
ret = $element[v](args[0]);
|
|
} else if (length == 2) {
|
|
ret = $element[v](args[0], args[1]);
|
|
} else if (length == 3) {
|
|
ret = $element[v](args[0], args[1], args[2]);
|
|
} else if (length == 4) {
|
|
ret = $element[v](args[0], args[1], args[2], args[3]);
|
|
}
|
|
// if the $element of an oxui object was returned
|
|
// then return the oxui object instead
|
|
// so we can do oxObj.jqFn().oxFn()
|
|
//Ox.print("v", v, "arguments", arguments)
|
|
if (ret.jquery) {
|
|
//Ox.print("ret", ret, "ret.data('id')", ret.data("ox"))
|
|
}
|
|
return ret.jquery && oxui.elements[id = ret.data("ox")] ?
|
|
oxui.elements[id] : ret;
|
|
}
|
|
});
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.theme()
|
|
get theme
|
|
Ox.theme("foo")
|
|
set theme to "foo"
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.theme = function() {
|
|
var length = arguments.length,
|
|
classes = $body.attr("class").split(" "),
|
|
arg, theme;
|
|
$.each(classes, function(i, v) {
|
|
if (Ox.startsWith(v, "OxTheme")) {
|
|
theme = v.replace("OxTheme", "").toLowerCase();
|
|
if (length == 1) {
|
|
$body.removeClass(v);
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
if (length == 1) {
|
|
arg = arguments[0]
|
|
$body.addClass("OxTheme" + Ox.toTitleCase(arg));
|
|
if (theme) {
|
|
$("input[type=image]").each(function() {
|
|
var $this = $(this);
|
|
$this.attr({
|
|
src: $this.attr("src").replace(
|
|
"/ox.ui." + theme + "/", "/ox.ui." + arg + "/"
|
|
)
|
|
});
|
|
});
|
|
$(".OxLoadingIcon").each(function() {
|
|
var $this = $(this);
|
|
$this.attr({
|
|
src: $this.attr("src").replace(
|
|
"/ox.ui." + theme + "/", "/ox.ui." + arg + "/"
|
|
)
|
|
});
|
|
})
|
|
}
|
|
}
|
|
return theme;
|
|
};
|
|
|
|
/*
|
|
============================================================================
|
|
Bars
|
|
============================================================================
|
|
*/
|
|
|
|
Ox.Bar = function(options, self) {
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
orientation: "horizontal",
|
|
size: "medium" // can be int
|
|
})
|
|
.options(options || {})
|
|
.addClass("OxBar Ox" + Ox.toTitleCase(self.options.orientation)),
|
|
dimensions = oxui.getDimensions(self.options.orientation);
|
|
self.options.size = Ox.isString(self.options.size) ?
|
|
oxui.getBarSize(self.options.size) : self.options.size;
|
|
that.css(dimensions[0], "100%")
|
|
.css(dimensions[1], self.options.size + "px");
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Resizebar
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Resizebar = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
collapsed: false,
|
|
collapsible: true,
|
|
edge: "left",
|
|
elements: [],
|
|
orientation: "horizontal",
|
|
parent: null,
|
|
resizable: true,
|
|
resize: [],
|
|
size: 0
|
|
})
|
|
.options(options || {}) // fixme: options function should be able to handle undefined, no need for || {}
|
|
.addClass("OxResizebar Ox" + Ox.toTitleCase(self.options.orientation))
|
|
/*
|
|
.attr({
|
|
draggable: "true"
|
|
})
|
|
.bind("dragstart", function(e) {
|
|
// e.originalEvent.dataTransfer.setDragImage($("<div>")[0], 0, 0);
|
|
})
|
|
.bind("drag", function(e) {
|
|
Ox.print("dragging", e)
|
|
})
|
|
*/
|
|
.mousedown(dragStart)
|
|
.dblclick(toggle)
|
|
.append($("<div>").addClass("OxSpace"))
|
|
.append($("<div>").addClass("OxLine"))
|
|
.append($("<div>").addClass("OxSpace"));
|
|
|
|
$.extend(self, {
|
|
clientXY: self.options.orientation == "horizontal" ? "clientY" : "clientX",
|
|
dimensions: oxui.getDimensions(self.options.orientation), // fixme: should orientation be the opposite orientation here?
|
|
edges: oxui.getEdges(self.options.orientation),
|
|
ids: $.map(self.options.elements, function(v, i) {
|
|
return v.options("id");
|
|
}),
|
|
length: self.options.resize.length,
|
|
startPos: 0,
|
|
startSize: 0
|
|
});
|
|
|
|
function drag(e) {
|
|
var d = e[self.clientXY] - self.startPos, i;
|
|
self.options.size = Ox.limit(self.startSize + d, self.options.resize[0], self.options.resize[self.length - 1]);
|
|
Ox.print("sS", self.startSize, "d", d, "s.o.s", self.options.size)
|
|
$.each(self.options.resize, function(i, v) {
|
|
if (self.options.size > v - 8 && self.options.size < v + 8) {
|
|
self.options.size = v;
|
|
return false;
|
|
}
|
|
});
|
|
that.css(self.edges[2], self.options.size + "px");
|
|
self.options.elements[0].css(self.dimensions[1], self.options.size + "px");
|
|
self.options.elements[1].css(self.edges[2], (self.options.size + 1) + "px");
|
|
Ox.Event.trigger("resize_" + self.ids[0], self.options.size);
|
|
Ox.Event.trigger("resize_" + self.ids[1], self.options.elements[1][self.dimensions[1]]());
|
|
}
|
|
|
|
function dragStart(e) {
|
|
self.startPos = e[self.clientXY];
|
|
self.startSize = self.options.size;
|
|
Ox.print("startSize", self.startSize)
|
|
$window.mousemove(drag);
|
|
$window.mouseup(dragStop);
|
|
}
|
|
|
|
function dragStop() {
|
|
$window.unbind("mousemove");
|
|
$window.unbind("mouseup");
|
|
}
|
|
|
|
function toggle() {
|
|
Ox.print("toggle");
|
|
var size = self.options.collapsed ? 0 : -self.options.size,
|
|
animate = {};
|
|
Ox.print("s.o.e", self.options.edge);
|
|
animate[self.options.edge] = size;
|
|
self.options.parent.animate(animate, 200, function() {
|
|
var i = (self.options.edge == "left" || self.options.edge == "top") ? 1 : 0;
|
|
Ox.Event.trigger("resize_" + self.ids[i], self.options.elements[i][self.dimensions[1]]());
|
|
self.options.collapsed = !self.options.collapsed;
|
|
});
|
|
}
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Tabbar
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Tabbar = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Bar({
|
|
size: 20
|
|
}, self)
|
|
.defaults({
|
|
selected: 0,
|
|
tabs: []
|
|
})
|
|
.options(options || {})
|
|
.addClass("OxTabbar");
|
|
|
|
Ox.ButtonGroup({
|
|
buttons: self.options.tabs,
|
|
group: true,
|
|
selectable: true,
|
|
selected: self.options.selected,
|
|
size: "medium",
|
|
style: "tab",
|
|
}).appendTo(that);
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
// fixme: no need for this
|
|
Ox.Toolbar = function(options, self) {
|
|
var self = self || {},
|
|
that = new Ox.Bar({
|
|
size: oxui.getBarSize(options.size)
|
|
}, self);
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
============================================================================
|
|
Ox.Dialog
|
|
============================================================================
|
|
*/
|
|
|
|
Ox.Dialog = function(options, self) {
|
|
|
|
// fixme: dialog should be derived from a generic draggable
|
|
var self = self || {},
|
|
that = new Ox.Element("div", self)
|
|
.defaults({
|
|
title: "",
|
|
buttons: [],
|
|
height: 216,
|
|
minHeight: 144,
|
|
minWidth: 256,
|
|
width: 384
|
|
})
|
|
.options(options || {})
|
|
.addClass("OxDialog");
|
|
|
|
if (!Ox.isArray(self.options.buttons[0])) {
|
|
self.options.buttons = [[], self.options.buttons];
|
|
}
|
|
|
|
that.$titlebar = new Ox.Bar({
|
|
size: "medium"
|
|
})
|
|
.addClass("OxTitleBar")
|
|
//.html(self.options.title)
|
|
.mousedown(drag)
|
|
.dblclick(center)
|
|
.appendTo(that);
|
|
that.$title = new Ox.Element()
|
|
.addClass("OxTitle")
|
|
.html(self.options.title)
|
|
.appendTo(that.$titlebar);
|
|
that.$content = new Ox.Container()
|
|
.addClass("OxContent")
|
|
.appendTo(that);
|
|
that.$buttonsbar = new Ox.Bar({})
|
|
.addClass("OxButtonsBar")
|
|
.appendTo(that);
|
|
that.$buttons = [];
|
|
$.each(self.options.buttons[0], function(i, button) {
|
|
that.$buttons[i] = new Ox.Button({
|
|
size: "medium",
|
|
value: button.value
|
|
})
|
|
.addClass("OxLeft")
|
|
.click(button.click) // fixme: rather use event?
|
|
.appendTo(that.$buttonsbar);
|
|
});
|
|
that.$resize = new Ox.Element()
|
|
.addClass("OxResize")
|
|
.mousedown(resize)
|
|
.dblclick(reset)
|
|
.appendTo(that.$buttonsbar);
|
|
$.each(self.options.buttons[1].reverse(), function(i, button) {
|
|
that.$buttons[that.$buttons.length] = new Ox.Button({
|
|
size: "medium",
|
|
value: button.value
|
|
})
|
|
.addClass("OxRight")
|
|
.click(button.click) // fixme: rather use event?
|
|
.appendTo(that.$buttonsbar);
|
|
});
|
|
that.$buttons[0].focus();
|
|
that.$layer = new Ox.Element() // fixme: Layer widget, that would handle click?
|
|
.addClass("OxLayer")
|
|
.mousedown(mousedownLayer)
|
|
.mouseup(mouseupLayer);
|
|
|
|
function center() {
|
|
that.css({
|
|
left: 0,
|
|
top: parseInt(-$document.height() / 10) + "px", // fixme: don't overlap menu
|
|
right: 0,
|
|
bottom: 0,
|
|
margin: "auto"
|
|
});
|
|
}
|
|
|
|
function drag(event) {
|
|
var bodyWidth = $body.width(),
|
|
bodyHeight = $document.height(),
|
|
elementWidth = that.width(),
|
|
offset = that.offset(),
|
|
x = event.clientX,
|
|
y = event.clientY;
|
|
$window.mousemove(function(event) {
|
|
/*
|
|
$("*").css({
|
|
WebkitUserSelect: "none"
|
|
});
|
|
*/
|
|
that.css({
|
|
margin: 0
|
|
});
|
|
var left = Ox.limit(
|
|
offset.left - x + event.clientX,
|
|
24 - elementWidth, bodyWidth - 24
|
|
//0, documentWidth - elementWidth
|
|
),
|
|
top = Ox.limit(
|
|
offset.top - y + event.clientY,
|
|
24, bodyHeight - 24
|
|
//24, documentHeight - elementHeight
|
|
);
|
|
that.css({
|
|
left: left + "px",
|
|
top: top + "px"
|
|
});
|
|
});
|
|
$window.one("mouseup", function() {
|
|
$window.unbind("mousemove");
|
|
/*
|
|
$("*").css({
|
|
WebkitUserSelect: "auto"
|
|
});
|
|
*/
|
|
});
|
|
}
|
|
|
|
function mousedownLayer() {
|
|
that.$layer.stop().animate({
|
|
opacity: 0.5
|
|
}, 0);
|
|
}
|
|
|
|
function mouseupLayer() {
|
|
that.$layer.stop().animate({
|
|
opacity: 0
|
|
}, 0);
|
|
}
|
|
|
|
function reset() {
|
|
that.css({
|
|
left: Math.max(that.offset().left, 24 - self.options.width)
|
|
})
|
|
.width(self.options.width)
|
|
.height(self.options.height);
|
|
that.$content.height(self.options.height - 80);
|
|
}
|
|
|
|
function resize(event) {
|
|
var contentHeight = that.$content.height(),
|
|
documentWidth = $document.width(),
|
|
documentHeight = $document.height(),
|
|
elementWidth = that.width(),
|
|
elementHeight = that.height(),
|
|
offset = that.offset(),
|
|
x = event.clientX,
|
|
y = event.clientY;
|
|
$window.mousemove(function(event) {
|
|
/*
|
|
$("*").css({
|
|
WebkitUserSelect: "none"
|
|
});
|
|
*/
|
|
that.css({
|
|
left: offset.left,
|
|
top: offset.top,
|
|
margin: 0
|
|
});
|
|
var width = Ox.limit(
|
|
elementWidth - x + event.clientX,
|
|
self.options.minWidth, Math.min(documentWidth, documentWidth - offset.left)
|
|
),
|
|
height = Ox.limit(
|
|
elementHeight - y + event.clientY,
|
|
self.options.minHeight, documentHeight - offset.top
|
|
);
|
|
that.width(width);
|
|
that.height(height);
|
|
that.$content.height(height - 80);
|
|
});
|
|
$window.one("mouseup", function() {
|
|
$window.unbind("mousemove");
|
|
/*
|
|
$("*").css({
|
|
WebkitUserSelect: "auto"
|
|
});
|
|
*/
|
|
});
|
|
}
|
|
|
|
self.onChange = function(key, value) {
|
|
if (key == "title") {
|
|
that.$title.html(value);
|
|
}
|
|
}
|
|
|
|
that.append = function($element) {
|
|
that.$content.append($element);
|
|
return that;
|
|
}
|
|
|
|
that.close = function(callback) {
|
|
callback = callback || function() {};
|
|
that.animate({
|
|
opacity: 0
|
|
}, 200, function() {
|
|
that.remove();
|
|
that.$layer.remove();
|
|
callback();
|
|
});
|
|
$window.unbind("mouseup", mouseupLayer)
|
|
return that;
|
|
}
|
|
|
|
that.disable = function() {
|
|
// to be used on submit of form, like login
|
|
that.$layer.addClass("OxFront");
|
|
};
|
|
|
|
that.enable = function() {
|
|
that.$layer.removeClass("OxFront");
|
|
}
|
|
|
|
that.open = function() {
|
|
that.$layer.appendTo($body);
|
|
center();
|
|
reset();
|
|
that.css({
|
|
opacity: 0
|
|
}).appendTo($body).animate({
|
|
opacity: 1
|
|
}, 200);
|
|
$window.bind("mouseup", mouseupLayer)
|
|
return that;
|
|
}
|
|
|
|
return that;
|
|
|
|
}
|
|
|
|
/*
|
|
============================================================================
|
|
Forms
|
|
============================================================================
|
|
*/
|
|
|
|
Ox.Form = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element("div", self)
|
|
.defaults({
|
|
items: []
|
|
})
|
|
.options(options || {}); // fixme: the || {} can be done once, in the options function
|
|
|
|
$.each(self.options.items, function(i, item) {
|
|
|
|
});
|
|
|
|
that.values = function() {
|
|
var values = {};
|
|
if (arguments.length == 0) {
|
|
$.each(self.options.items, function(i, item) {
|
|
values[item.id] = item.val();
|
|
});
|
|
return values;
|
|
} else {
|
|
$.each(arguments[0], function(key, value) {
|
|
|
|
});
|
|
return that;
|
|
}
|
|
};
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
Ox.FormItem = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element("", self)
|
|
.defaults({
|
|
error: "",
|
|
regexp: / /,
|
|
size: "medium",
|
|
type: "text"
|
|
})
|
|
.options(options || {});
|
|
|
|
that.$input = new OxInput();
|
|
|
|
return that;
|
|
|
|
}
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Button
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Button = function(options, self) {
|
|
/*
|
|
events:
|
|
click non-selectable button was clicked
|
|
deselect selectable button was deselected
|
|
select selectable button was selected
|
|
*/
|
|
var self = self || {},
|
|
that = new Ox.Element("input", self)
|
|
.defaults({
|
|
disabled: false,
|
|
group: null,
|
|
id: "",
|
|
selectable: false,
|
|
selected: false,
|
|
size: "medium",
|
|
style: "default", // can be default, symbol or tab
|
|
type: "text",
|
|
value: "",
|
|
values: [] // fixme: shouldn't this go into self.values?
|
|
})
|
|
.options($.extend(options, {
|
|
value: $.isArray(options.value) ?
|
|
options.value[0] : options.value,
|
|
values: $.makeArray(options.value)
|
|
}))
|
|
.attr({
|
|
disabled: self.options.disabled ? "disabled" : "",
|
|
type: self.options.type == "text" ? "button" : "image"
|
|
})
|
|
.addClass("OxButton Ox" + Ox.toTitleCase(self.options.size) +
|
|
(self.options.style != "default" ? " Ox" + Ox.toTitleCase(self.options.style) : "") +
|
|
(self.options.disabled ? " OxDisabled": "") +
|
|
(self.options.selected ? " OxSelected": ""))
|
|
.mousedown(mousedown)
|
|
.click(click);
|
|
//Ox.print(self.options.value, self.options.disabled)
|
|
/*
|
|
that.bind("OxElement" + that.id + "SetOptions", function(e, data) {
|
|
if (typeof data.selected != "undefined") {
|
|
if (data.selected != that.hasClass("OxSelected")) {
|
|
that.toggleClass("OxSelected");
|
|
}
|
|
}
|
|
if (typeof data.value != "undefined") {
|
|
if (self.options.type == "image") {
|
|
that.attr({
|
|
src: oxui.path + "png/" + Ox.theme() +
|
|
"/button" + Ox.toTitleCase(options.value) + ".png"
|
|
});
|
|
} else {
|
|
that.val(self.options.value);
|
|
}
|
|
}
|
|
})
|
|
*/
|
|
function mousedown(e) {
|
|
if (self.options.type == "image" && $.browser.safari) {
|
|
// keep image from being draggable
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
function click() {
|
|
if (!self.options.selectable) {
|
|
that.triggerEvent("click");
|
|
} else if (!self.options.group || !self.options.selected) {
|
|
if (self.options.group) {
|
|
that.triggerEvent("select");
|
|
} else {
|
|
that.toggleSelected();
|
|
}
|
|
}
|
|
if (self.options.values.length == 2) {
|
|
that.options({
|
|
value: self.options.value == self.options.values[0] ?
|
|
self.options.values[1] : self.options.values[0]
|
|
});
|
|
}
|
|
//self.options.click();
|
|
}
|
|
self.onChange = function(key, value) {
|
|
//Ox.print("setOption", option, value)
|
|
if (key == "selected") {
|
|
if (value != that.hasClass("OxSelected")) { // fixme: neccessary?
|
|
that.toggleClass("OxSelected");
|
|
}
|
|
that.triggerEvent("change");
|
|
} else if (key == "value") {
|
|
if (self.options.type == "image") {
|
|
that.attr({
|
|
src: oxui.path + "png/ox.ui." + Ox.theme() +
|
|
"/button" + Ox.toTitleCase(value) + ".png"
|
|
});
|
|
} else {
|
|
that.val(value);
|
|
}
|
|
}
|
|
}
|
|
that.toggleDisabled = function() {
|
|
that.options({
|
|
enabled: !self.options.disabled
|
|
});
|
|
}
|
|
that.toggleSelected = function() {
|
|
that.options({
|
|
selected: !self.options.selected
|
|
});
|
|
}
|
|
that.options("value", self.options.value);
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.ButtonGroup
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.ButtonGroup = function(options, self) {
|
|
|
|
/*
|
|
events:
|
|
change {id, value} selection within a group changed
|
|
*/
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
buttons: [],
|
|
group: false,
|
|
selectable: false,
|
|
selected: -1,
|
|
size: "medium",
|
|
style: "",
|
|
type: "text",
|
|
})
|
|
.options(options || {})
|
|
.addClass("OxButtonGroup");
|
|
self.position = {};
|
|
|
|
that.$buttons = [];
|
|
$.each(self.options.buttons, function(position, button) {
|
|
that.$buttons[position] = Ox.Button({
|
|
disabled: button.disabled,
|
|
group: self.options.group ? that : null,
|
|
id: button.id,
|
|
selectable: self.options.selectable,
|
|
selected: position == self.options.selected,
|
|
size: self.options.size,
|
|
style: self.options.style,
|
|
type: self.options.type,
|
|
value: button.value
|
|
}).appendTo(that);
|
|
self.position[that.$buttons.id] = position;
|
|
that.bindEvent("select_" + that.$buttons[position].options("id"), function() {
|
|
selectButton(position);
|
|
});
|
|
});
|
|
|
|
function onChange(event, data) {
|
|
console.log("event", event, "data", data)
|
|
var id = event.split("_")[1];
|
|
if (self.options.selected > -1) {
|
|
that.$buttons[self.options.selected].toggleSelected();
|
|
}
|
|
self.options.selected = self.position[id];
|
|
that.triggerEvent("change", {
|
|
value: id
|
|
});
|
|
}
|
|
|
|
function selectButton(position) {
|
|
that.$buttons[self.options.selected].toggleSelected();
|
|
self.options.selected = position;
|
|
that.$buttons[self.options.selected].toggleSelected();
|
|
};
|
|
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Input
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Input = function(options, self) {
|
|
|
|
/* options:
|
|
* autocomplete function, or array of values, or dict with array of values per label or placeholder
|
|
* clear boolean, clear button, or not
|
|
* highlight boolean, highlight value in autocomplete menu, or not
|
|
* id
|
|
* label string or array (select) -- label and placeholder are mutually exclusive
|
|
* labelWidth integer (px)
|
|
* placeholder string or array (select) -- label and placeholder are mutually exclusive
|
|
* selected integer, selected label or placeholder
|
|
* size "large", "medium" or "small"
|
|
* type "text", "password", "textarea", etc.
|
|
*/
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element("div", self)
|
|
.defaults({
|
|
autocomplete: null,
|
|
clear: false,
|
|
highlight: false,
|
|
id: "",
|
|
label: "",
|
|
labelWidth: 64,
|
|
placeholder: "",
|
|
selected: 0,
|
|
size: "medium",
|
|
type: "text"
|
|
})
|
|
.options(options || {})
|
|
.addClass("OxInput Ox" + Ox.toTitleCase(self.options.size)),
|
|
autocomplete; // fixme: should be self.autocomplete
|
|
|
|
if (self.options.label) {
|
|
self.options.label = Ox.makeArray(self.options.label);
|
|
self.option = self.options.label[self.options.selected]; // fixme: id or title? or not use this at all?
|
|
self.items = self.options.label;
|
|
} else if (self.options.placeholder) {
|
|
self.options.placeholder = Ox.makeArray(self.options.placeholder);
|
|
self.option = self.options.placeholder[self.options.selected];
|
|
self.items = self.options.placeholder;
|
|
}
|
|
if (Ox.isArray(self.options.autocomplete)) {
|
|
autocomplete = self.options.autocomplete;
|
|
self.options.autocomplete = {};
|
|
self.options.autocomplete[self.placeholder] = autocomplete;
|
|
}
|
|
|
|
if (self.options.label) {
|
|
that.$label = new Ox.Element()
|
|
.addClass("OxInputLabel")
|
|
.width(self.options.labelWidth)
|
|
.html(self.options.label[0].title)
|
|
.appendTo(that);
|
|
}
|
|
if (self.options.label.length > 1 || self.options.placeholder.length > 1) {
|
|
that.$label && that.$label.click(select);
|
|
that.$select = new Ox.Button({
|
|
style: "symbol",
|
|
type: "image",
|
|
value: "select"
|
|
// value: oxui.symbols.select
|
|
})
|
|
.click(select)
|
|
.appendTo(that);
|
|
self.selectId = Ox.toCamelCase(
|
|
self.options.id + "_" + (self.options.label.length > 1 ? "label" : "placeholder")
|
|
);
|
|
self.selectMenu = new Ox.Menu({
|
|
element: that,
|
|
id: self.selectId,
|
|
items: $.map(self.items, function(item, position) {
|
|
return {
|
|
checked: position == self.options.selected,
|
|
id: item.id,
|
|
group: self.selectId, // fixme: same id, works here, but should be different
|
|
title: item.title
|
|
};
|
|
}),
|
|
offset: {
|
|
left: 4,
|
|
top: 0
|
|
}
|
|
});
|
|
that.bindEvent("change_" + self.selectId, change);
|
|
}
|
|
|
|
that.$input = new Ox.Element(
|
|
self.options.type == "textarea" ? "textarea" : "input", self
|
|
)
|
|
.attr({
|
|
type: self.options.type == "textarea" ? undefined : self.options.type // fixme: make conditional?
|
|
})
|
|
.addClass(
|
|
"OxInput Ox" + Ox.toTitleCase(self.options.size) +
|
|
" OxPlaceholder"
|
|
)
|
|
.focus(focus)
|
|
.blur(blur)
|
|
.change(change)
|
|
.appendTo(that);
|
|
|
|
self.options.placeholder && that.$input.val(self.option);
|
|
|
|
if (self.options.clear) {
|
|
that.$clear = new Ox.Button({
|
|
style: "symbol",
|
|
type: "image",
|
|
value: "clear"
|
|
//value: oxui.symbols.clear
|
|
})
|
|
.click(clear)
|
|
.appendTo(that);
|
|
}
|
|
|
|
if (self.options.autocomplete) {
|
|
that.$input.attr({
|
|
autocomplete: "off"
|
|
});
|
|
self.autocompleteId = self.options.id + "_menu"; // fixme: we do this in other places ... are we doing it the same way? var name?
|
|
self.autocompleteMenu = new Ox.Menu({
|
|
element: that.$input,
|
|
id: self.autocompleteId,
|
|
offset: {
|
|
left: 4,
|
|
top: 0
|
|
},
|
|
size: self.options.size
|
|
});
|
|
that.bindEvent("click_" + self.autocompleteId, onClick);
|
|
}
|
|
|
|
if (self.options.type != "textarea") {
|
|
that.bindEvent({
|
|
key_enter: submit,
|
|
});
|
|
}
|
|
that.bindEvent({
|
|
key_escape: cancel
|
|
});
|
|
|
|
function autocomplete(value, callback) {
|
|
var value = value.toLowerCase(),
|
|
items = [];
|
|
if (value === "") {
|
|
// items = self.options.autocomplete[self.placeholder];
|
|
} else {
|
|
$.each(self.options.autocomplete[self.option], function(i, item) {
|
|
if (item.toLowerCase().indexOf(value) > -1) {
|
|
items.push(item);
|
|
}
|
|
});
|
|
}
|
|
callback(items);
|
|
}
|
|
|
|
function blur() {
|
|
that.loseFocus();
|
|
if (self.options.placeholder && that.$input.val() === "") {
|
|
that.$input.addClass("OxPlaceholder").val(self.option);
|
|
}
|
|
if (self.options.autocomplete) {
|
|
$document.unbind("keydown", keypress);
|
|
$document.unbind("keypress", keypress);
|
|
}
|
|
}
|
|
|
|
function call() {
|
|
var value = that.$input.val();
|
|
Ox.print("autocomplete call", self.option, value)
|
|
if (self.options.autocomplete) {
|
|
if (value !== "") {
|
|
Ox.isFunction(self.options.autocomplete) ? (
|
|
self.option ?
|
|
self.options.autocomplete(self.option.id, value, callback) :
|
|
self.options.autocomplete(value, callback)
|
|
) : autocomplete(value, callback);
|
|
} else {
|
|
callback();
|
|
}
|
|
}
|
|
}
|
|
|
|
function callback(items) {
|
|
Ox.print("autocomplete callback", items)
|
|
var items = items || [],
|
|
selected = items.length == 1 ? 0 : -1,
|
|
value = that.$input.val().toLowerCase();
|
|
if (items.length) {
|
|
items = $.map(items, function(title, position) {
|
|
if (value == Ox.stripTags(title.toLowerCase())) {
|
|
selected = position;
|
|
}
|
|
return {
|
|
id: title.toLowerCase(), // fixme: need function to do lowercase, underscores etc?
|
|
title: self.options.highlight ? title.replace(
|
|
new RegExp("(" + value + ")", "ig"),
|
|
"<span class=\"OxHighlight\">$1</span>"
|
|
) : title
|
|
};
|
|
});
|
|
self.selectMenu.hideMenu();
|
|
self.autocompleteMenu.options({
|
|
items: items,
|
|
selected: selected
|
|
}).showMenu();
|
|
} else {
|
|
self.autocompleteMenu.hideMenu();
|
|
}
|
|
}
|
|
|
|
function cancel() {
|
|
that.$input.blur();
|
|
}
|
|
|
|
function change(event, data) {
|
|
Ox.print("input change", event, data)
|
|
if (data) {
|
|
self.option = {
|
|
id: data.id,
|
|
title: data.value // fixme: should be data.title
|
|
};
|
|
}
|
|
if (self.options.label) {
|
|
that.$label.html(self.option.title);
|
|
that.$input.focus();
|
|
call();
|
|
} else {
|
|
if (that.$input.is(".OxPlaceholder")) {
|
|
that.$input.val(self.option);
|
|
//that.$input.focus();
|
|
} else {
|
|
that.$input.focus();
|
|
call();
|
|
}
|
|
}
|
|
}
|
|
|
|
function clear() {
|
|
that.$input.val("").focus();
|
|
//call();
|
|
}
|
|
|
|
function focus() {
|
|
var value;
|
|
that.gainFocus();
|
|
if (that.$input.is(".OxPlaceholder")) {
|
|
that.$input.val("").removeClass("OxPlaceholder");
|
|
}
|
|
value = that.$input.val();
|
|
if (self.options.autocomplete) {
|
|
// fixme: different in webkit and firefox (?), see keyboard handler, need generic function
|
|
$document.bind("keydown", keypress);
|
|
$document.bind("keypress", keypress);
|
|
value !== "" && Ox.isFunction(self.options.autocomplete) ?
|
|
self.options.autocomplete(self.option.id, value, callback) :
|
|
autocomplete(value, callback);
|
|
}
|
|
}
|
|
|
|
function keypress(event) {
|
|
if (event.keyCode != 13) {
|
|
setTimeout(function() {
|
|
var value = that.$input.val();
|
|
if (value != self.value) {
|
|
self.value = value;
|
|
call();
|
|
}
|
|
}, 25);
|
|
}
|
|
}
|
|
|
|
function onClick(event, data) {
|
|
Ox.print("onClick", data);
|
|
that.$input.val(Ox.stripTags(data.title));
|
|
self.autocompleteMenu.hideMenu();
|
|
submit();
|
|
}
|
|
|
|
function select() {
|
|
self.selectMenu.showMenu();
|
|
}
|
|
|
|
function selection() {
|
|
// fixme: not used!
|
|
var start, end;
|
|
if (arguments.length == 0) {
|
|
return [self.element.selectionStart, self.element.selectionEnd];
|
|
} else {
|
|
start = arguments[0];
|
|
end = arguments[1] || start;
|
|
self.element.setSelectionRange(start, end);
|
|
}
|
|
}
|
|
|
|
function submit() {
|
|
Ox.print("input submit", that.$input.val())
|
|
that.$input.trigger("blur");
|
|
that.triggerEvent("submit", self.option ? {
|
|
key: self.option.id,
|
|
value: that.$input.val()
|
|
} : that.$input.val());
|
|
}
|
|
|
|
that.changeLabel = function(id) {
|
|
that.$label.html(Ox.getObjectById(self.options.label, id).title);
|
|
self.selectMenu.checkItem(id);
|
|
};
|
|
|
|
that.height = function(value) {
|
|
var stop = 8 / value;
|
|
if (self.options.type == "textarea") {
|
|
that.$element
|
|
.height(value)
|
|
.css({
|
|
background: "-moz-linear-gradient(top, rgb(224, 224, 224), rgb(208, 208, 208) " + (stop * 100) + "%, rgb(208, 208, 208) " + (100 - stop * 100) + "%, rgb(192, 192, 192))"
|
|
})
|
|
.css({
|
|
background: "-webkit-gradient(linear, left top, left bottom, from(rgb(224, 224, 224)), color-stop(" + stop + ", rgb(208, 208, 208)), color-stop(" + (1 - stop) + ", rgb(208, 208, 208)), to(rgb(192, 192, 192)))"
|
|
});
|
|
that.$input
|
|
.height(value)
|
|
.css({
|
|
background: "-moz-linear-gradient(top, rgb(224, 224, 224), rgb(240, 240, 240) " + (stop * 100) + "%, rgb(240, 240, 240) " + (100 - stop * 100) + "%, rgb(255, 255, 255))"
|
|
})
|
|
.css({
|
|
background: "-webkit-gradient(linear, left top, left bottom, from(rgb(224, 224, 224)), color-stop(" + stop + ", rgb(240, 240, 240)), color-stop(" + (1 - stop) + ", rgb(240, 240, 240)), to(rgb(255, 255, 255)))"
|
|
});
|
|
}
|
|
return that;
|
|
}
|
|
|
|
that.width = function(value) {
|
|
that.$element.width(value);
|
|
that.$input.width(value - (self.options.type == "textarea" ? 0 : 2) -
|
|
(self.options.label ? self.options.labelWidth + 18 : 0) -
|
|
(self.options.placeholder.length > 1 ? 26 : 0) -
|
|
(self.options.clear ? 31 : 0));
|
|
// fixme: the values above are all weird guesswork
|
|
return that;
|
|
}
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Label
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Label = function(options, self) {
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
id: "",
|
|
title: ""
|
|
})
|
|
.options(options)
|
|
.addClass("OxLabel");
|
|
that.html(self.options.title);
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Range
|
|
|
|
options:
|
|
animate boolean if true, animate thumb
|
|
arrows boolean if true, show arrows
|
|
arrowStep number step when clicking arrows
|
|
arrowSymbols array arrow symbols, like ["minus", "plus"]
|
|
max number maximum value
|
|
min number minimum value
|
|
orientation string "horizontal" or "vertical"
|
|
step number step between values
|
|
size number width or height, in px
|
|
thumbSize number minimum width or height of thumb, in px
|
|
thumbValue boolean if true, display value on thumb
|
|
trackImages string or array one or multiple track background image URLs
|
|
trackStep number 0 (scroll here) or step when clicking track
|
|
value number initial value
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Range = function(options, self) {
|
|
|
|
/*
|
|
init
|
|
*/
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
animate: false,
|
|
arrows: false,
|
|
arrowStep: 1,
|
|
arrowSymbols: ["previous", "next"],
|
|
max: 100,
|
|
min: 0,
|
|
orientation: "horizontal",
|
|
step: 1,
|
|
size: 128,
|
|
thumbSize: 16,
|
|
thumbValue: false,
|
|
trackImages: [],
|
|
trackStep: 0,
|
|
value: 0
|
|
})
|
|
.options($.extend(options, {
|
|
arrowStep: options.arrowStep ?
|
|
options.arrowStep : options.step,
|
|
trackImages: $.makeArray(options.trackImages || [])
|
|
}))
|
|
.addClass("OxRange");
|
|
|
|
// fixme: self. ... ?
|
|
var trackImages = self.options.trackImages.length,
|
|
values = (self.options.max - self.options.min + self.options.step) /
|
|
self.options.step;
|
|
|
|
/*
|
|
construct
|
|
*/
|
|
that.$element
|
|
.css({
|
|
width: self.options.size + "px"
|
|
});
|
|
if (self.options.arrows) {
|
|
var $arrowDec = Ox.Button({
|
|
style: "symbol",
|
|
type: "image",
|
|
value: self.options.arrowSymbols[0]
|
|
})
|
|
.addClass("OxArrow")
|
|
.mousedown(mousedownArrow)
|
|
.click(clickArrowDec)
|
|
.appendTo(that.$element);
|
|
}
|
|
var $track = new Ox.Element()
|
|
.addClass("OxTrack")
|
|
.mousedown(clickTrack)
|
|
.appendTo(that.$element); // fixme: make that work
|
|
|
|
if (trackImages) {
|
|
var width = parseFloat(screen.width / trackImages),
|
|
$image = $("<canvas/>")
|
|
.attr({
|
|
width: width * trackImages,
|
|
height: 14
|
|
})
|
|
.addClass("OxImage")
|
|
.appendTo($track.$element), // fixme: make that work
|
|
c = $image[0].getContext('2d');
|
|
c.mozImageSmoothingEnabled = false; // we may want to remove this later
|
|
$.each(self.options.trackImages, function(i, v) {
|
|
$("<img/>")
|
|
.attr({
|
|
src: v
|
|
})
|
|
.load(function() {
|
|
c.drawImage(this, i * width, 0, width, 14);
|
|
});
|
|
});
|
|
}
|
|
var $thumb = Ox.Button({})
|
|
.addClass("OxThumb")
|
|
.appendTo($track);
|
|
if (self.options.arrows) {
|
|
var $arrowInc = Ox.Button({
|
|
style: "symbol",
|
|
type: "image",
|
|
value: self.options.arrowSymbols[1]
|
|
})
|
|
.addClass("OxArrow")
|
|
.mousedown(mousedownArrow)
|
|
.click(clickArrowInc)
|
|
.appendTo(that.$element);
|
|
}
|
|
var rangeWidth, trackWidth, imageWidth, thumbWidth;
|
|
setWidth(self.options.size);
|
|
|
|
/*
|
|
private functions
|
|
*/
|
|
|
|
function clickArrowDec() {
|
|
that.removeClass("OxActive");
|
|
setValue(self.options.value - self.options.arrowStep, 200)
|
|
}
|
|
function clickArrowInc() {
|
|
that.removeClass("OxActive");
|
|
setValue(self.options.value + self.options.arrowStep, 200);
|
|
}
|
|
function clickTrack(e) {
|
|
Ox.Focus.focus();
|
|
var left = $track.offset().left,
|
|
offset = $(e.target).hasClass("OxThumb") ?
|
|
e.clientX - $thumb.offset().left - thumbWidth / 2 - 2 : 0;
|
|
function val(e) {
|
|
return getVal(e.clientX - left - offset);
|
|
}
|
|
setValue(val(e), 200);
|
|
$window.mousemove(function(e) {
|
|
setValue(val(e));
|
|
});
|
|
$window.one("mouseup", function() {
|
|
$window.unbind("mousemove");
|
|
});
|
|
}
|
|
function getPx(val) {
|
|
var pxPerVal = (trackWidth - thumbWidth - 2) /
|
|
(self.options.max - self.options.min);
|
|
return Math.ceil((val - self.options.min) * pxPerVal + 1);
|
|
}
|
|
function getVal(px) {
|
|
var px = trackWidth / values >= 16 ? px : px - 8,
|
|
valPerPx = (self.options.max - self.options.min) /
|
|
(trackWidth - thumbWidth);
|
|
return Ox.limit(self.options.min +
|
|
Math.floor(px * valPerPx / self.options.step) * self.options.step,
|
|
self.options.min, self.options.max);
|
|
}
|
|
function mousedownArrow() {
|
|
that.addClass("OxActive");
|
|
}
|
|
function setThumb(animate) {
|
|
var animate = typeof animate != "undefined" ? animate : 0;
|
|
$thumb.animate({
|
|
marginLeft: (getPx(self.options.value) - 2) + "px",
|
|
width: thumbWidth + "px"
|
|
}, self.options.animate ? animate : 0, function() {
|
|
if (self.options.thumbValue) {
|
|
$thumb.options({
|
|
value: self.options.value
|
|
});
|
|
}
|
|
});
|
|
}
|
|
function setValue(val, animate) {
|
|
val = Ox.limit(val, self.options.min, self.options.max);
|
|
if (val != self.options.value) {
|
|
that.options({
|
|
value: val
|
|
});
|
|
setThumb(animate);
|
|
that.triggerEvent("change", { value: val });
|
|
}
|
|
}
|
|
function setWidth(width) {
|
|
trackWidth = width - self.options.arrows * 32;
|
|
thumbWidth = Math.max(trackWidth / values - 2, self.options.thumbSize - 2);
|
|
that.$element.css({
|
|
width: (width - 2) + "px"
|
|
});
|
|
$track.css({
|
|
width: (trackWidth - 2) + "px"
|
|
});
|
|
if (trackImages) {
|
|
$image.css({
|
|
width: (trackWidth - 2) + "px"
|
|
});
|
|
}
|
|
$thumb.css({
|
|
width: (thumbWidth - 2) + "px",
|
|
padding: 0
|
|
});
|
|
setThumb();
|
|
}
|
|
|
|
/*
|
|
shared functions
|
|
*/
|
|
|
|
self.onChange = function(option, value) {
|
|
|
|
}
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Select
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Select = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element("div", self) // fixme: do we use "div", or {}, or "", by default?
|
|
.defaults({
|
|
id: "",
|
|
items: [],
|
|
size: "medium"
|
|
})
|
|
.options(options)
|
|
.addClass("OxSelect Ox" + Ox.toTitleCase(self.options.size));
|
|
self.buttonId = self.options.id + "_button";
|
|
self.groupId = self.options.id; // + "_group"
|
|
self.menuId = self.options.id + "_menu",
|
|
|
|
$.each(self.options.items, function(i, item) {
|
|
self.options.items[i] = $.extend(self.options.items[i], {
|
|
checked: item.checked || false,
|
|
group: self.groupId
|
|
});
|
|
if (item.checked) {
|
|
self.selected = i;
|
|
}
|
|
});
|
|
|
|
Ox.print(self.options.id)
|
|
that.$button = new Ox.Button($.extend(self.options, {
|
|
id: self.buttonId,
|
|
type: "text", // fixme: this shouldn't be necessary
|
|
value: self.options.items[self.selected].title // fixme: title instead of value?
|
|
}), {})
|
|
.click(clickButton)
|
|
.appendTo(that);
|
|
|
|
that.$symbol = new Ox.Button({
|
|
style: "symbol",
|
|
type: "image",
|
|
value: "select"
|
|
})
|
|
.click(clickButton)
|
|
.appendTo(that);
|
|
|
|
that.$menu = new Ox.Menu({
|
|
element: that.$button,
|
|
id: self.menuId,
|
|
items: self.options.items,
|
|
offset: {
|
|
left: 8,
|
|
top: 0
|
|
},
|
|
side: "bottom",
|
|
size: self.options.size
|
|
});
|
|
|
|
that.bindEvent("change_" + self.groupId, clickMenu);
|
|
|
|
function clickButton() {
|
|
that.$menu.toggleMenu();
|
|
}
|
|
|
|
function clickMenu(event, data) {
|
|
that.$button.options({
|
|
value: data.value
|
|
});
|
|
that.triggerEvent("change", data.value);
|
|
}
|
|
|
|
self.onChange = function(key, value) {
|
|
|
|
};
|
|
|
|
that.selectItem = function(id) {
|
|
that.$button.options({
|
|
value: Ox.getObjectById(self.options.items, id).title
|
|
});
|
|
that.$menu.checkItem(id);
|
|
};
|
|
|
|
that.width = function(val) {
|
|
// fixme: silly hack, and won't work for css()
|
|
that.$element.width(val + 16);
|
|
that.$button.width(val);
|
|
//that.$symbol.width(val);
|
|
return that;
|
|
};
|
|
|
|
return that;
|
|
|
|
}
|
|
|
|
/*
|
|
============================================================================
|
|
Lists
|
|
============================================================================
|
|
*/
|
|
|
|
Ox.IconList = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
id: "",
|
|
item: function() {},
|
|
keys: [],
|
|
orientation: "both",
|
|
request: function() {},
|
|
size: 128,
|
|
sort: [],
|
|
})
|
|
.options(options || {});
|
|
|
|
$.extend(self, {
|
|
itemHeight: self.options.size * 1.5,
|
|
itemWidth: self.options.size
|
|
});
|
|
|
|
that.$element = new Ox.List({
|
|
construct: constructItem,
|
|
itemHeight: self.itemHeight,
|
|
itemWidth: self.itemWidth,
|
|
keys: $,
|
|
orientation: "both",
|
|
request: function() {},
|
|
rowLength: 1,
|
|
size: 128,
|
|
type: "icon",
|
|
}, self)
|
|
.click(click)
|
|
.dblclick(dblclick)
|
|
.scroll(scroll);
|
|
|
|
function click() {
|
|
|
|
}
|
|
|
|
function constructItem(data) {
|
|
var data = self.options.item(data, self.options.sort);
|
|
return new Ox.IconItem($.extend(data, {
|
|
size: self.options.size
|
|
}));
|
|
}
|
|
|
|
function dblclick() {
|
|
|
|
}
|
|
|
|
function scroll() {
|
|
|
|
}
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
Ox.IconItem = function(options, self) {
|
|
|
|
var self = self || {}
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
height: 0,
|
|
id: "",
|
|
info: "",
|
|
size: 128,
|
|
title: "",
|
|
width: 0,
|
|
url: ""
|
|
})
|
|
.options(options || {});
|
|
|
|
$.extend(self, {
|
|
height: self.options.size * 1.5,
|
|
url: oxui.path + "/png/ox.ui." + Ox.theme() + "/icon.png",
|
|
width: self.options.size + 4
|
|
});
|
|
|
|
that.css({
|
|
width: self.width + "px",
|
|
height: self.height + "px"
|
|
});
|
|
that.$icon = $("<div>")
|
|
.addClass("OxIcon")
|
|
.css({
|
|
top: self.options.size == 64 ? -70 : -128,
|
|
width: self.options.size + "px",
|
|
height: self.options.size + "px"
|
|
});
|
|
that.$iconImage = $("<img>")
|
|
.attr({
|
|
src: self.url
|
|
})
|
|
.css({
|
|
width: iconWidth + "px",
|
|
height: iconHeight + "px"
|
|
})
|
|
.mouseenter(mouseenter)
|
|
.mouseleave(mouseleave)
|
|
.one("load", function() {
|
|
that.$iconImage.attr({
|
|
src: self.options.url
|
|
});
|
|
});
|
|
that.$textBox = $("<div>")
|
|
.addClass("OxText")
|
|
.css({
|
|
top: (self.options.size / 2 + 2) + "px",
|
|
width: self.width + "px",
|
|
height: (self.options.size == 64 ? 38 : 58) + "px"
|
|
})
|
|
that.$text = $("<div>")
|
|
.html(self.options.title + "<br/><span class=\"OxInfo\">" + self.options.info + "</span>")
|
|
.mouseenter(mouseenter)
|
|
.mouseleave(mouseleave)
|
|
that.$reflection = $("<div>")
|
|
.addClass("OxReflection")
|
|
.css({
|
|
top: (self.options.size + 2) + "px",
|
|
width: self.options.size + "px",
|
|
height: (self.options.size / 2) + "px"
|
|
});
|
|
that.$reflectionImage = $("<img>")
|
|
.addClass("OxReflection")
|
|
.attr({
|
|
src: self.url
|
|
})
|
|
.css({
|
|
width: self.options.width + "px",
|
|
height: self.options.height + "px"
|
|
})
|
|
.one("load", function() {
|
|
that.$reflectionImage.attr({
|
|
src: self.options.url
|
|
});
|
|
});
|
|
that.$gradient = $("<div>")
|
|
.addClass("OxGradient")
|
|
.css({
|
|
top: (-self.options.size - 2) + "px"
|
|
});
|
|
|
|
that.append(
|
|
that.$reflection.append(
|
|
that.$reflectionImage
|
|
).append(
|
|
that.$gradientImage
|
|
)
|
|
).append(
|
|
that.$textBox.append(
|
|
that.$text
|
|
)
|
|
).append(
|
|
that.$icon.append(
|
|
that.$iconImage
|
|
)
|
|
);
|
|
|
|
function mouseenter() {
|
|
that.addClass("OxHover");
|
|
}
|
|
|
|
function mouseleave() {
|
|
that.removeClass("OxHover");
|
|
}
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
Ox.List = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Container({}, self)
|
|
.defaults({
|
|
construct: function() {},
|
|
itemHeight: 16,
|
|
itemWidth: 16,
|
|
keys: [],
|
|
orientation: "vertical",
|
|
request: function() {}, // {sort:, range:, callback:}, without parameter returns {items, size etc.}
|
|
rowLength: 1,
|
|
sort: [],
|
|
type: "text",
|
|
unique: ""
|
|
})
|
|
.options(options || {})
|
|
.click(click)
|
|
.scroll(scroll);
|
|
|
|
$.extend(self, {
|
|
$items: [],
|
|
$pages: [],
|
|
ids: {},
|
|
keyboardEvents: {
|
|
key_alt_control_a: invertSelection,
|
|
key_control_a: selectAll,
|
|
key_control_shift_a: selectNone,
|
|
key_end: scrollToFirst,
|
|
key_home: scrollToLast,
|
|
key_pagedown: scrollPageDown,
|
|
key_pageup: scrollPageUp
|
|
},
|
|
page: 0,
|
|
pageLength: 100,
|
|
requests: [],
|
|
selected: []
|
|
});
|
|
self.keyboardEvents["key_" + (self.options.orientation == "horizontal" ? "left" : "up")] = selectPrevious;
|
|
self.keyboardEvents["key_" + (self.options.orientation == "horizontal" ? "right" : "down")] = selectNext;
|
|
self.keyboardEvents["key_" + (self.options.orientation == "horizontal" ? "shift_left" : "shift_up")] = addPreviousToSelection;
|
|
self.keyboardEvents["key_" + (self.options.orientation == "horizontal" ? "shift_right" : "shift_down")] = addNextToSelection;
|
|
|
|
updateQuery();
|
|
Ox.print("s.o", self.options)
|
|
that.bindEvent(self.keyboardEvents);
|
|
|
|
function addAllToSelection(pos) {
|
|
var arr,
|
|
len = self.$items.length;
|
|
if (!isSelected(pos)) {
|
|
if (self.selected.length == 0) {
|
|
addToSelection(pos);
|
|
} else {
|
|
if (Ox.min(self.selected) < pos) {
|
|
var arr = [pos];
|
|
for (var i = pos - 1; i >= 0; i--) {
|
|
if (isSelected(i)) {
|
|
$.each(arr, function(i, v) {
|
|
addToSelection(v);
|
|
});
|
|
break;
|
|
}
|
|
arr.push(i);
|
|
}
|
|
}
|
|
if (Ox.max(self.selected) > pos) {
|
|
var arr = [pos];
|
|
for (var i = pos + 1; i < len; i++) {
|
|
if (isSelected(i)) {
|
|
$.each(arr, function(i, v) {
|
|
addToSelection(v);
|
|
});
|
|
break;
|
|
}
|
|
arr.push(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function addNextToSelection() {
|
|
var pos = getNext();
|
|
if (pos > -1) {
|
|
addToSelection(pos);
|
|
scrollTo(pos);
|
|
}
|
|
}
|
|
|
|
function addPreviousToSelection() {
|
|
var pos = getPrevious();
|
|
if (pos > -1) {
|
|
addToSelection(pos);
|
|
scrollTo(pos);
|
|
}
|
|
}
|
|
|
|
function addToSelection(pos) {
|
|
if (!isSelected(pos)) {
|
|
self.selected.push(pos);
|
|
if (!Ox.isUndefined(self.$items[pos])) {
|
|
self.$items[pos].addClass("OxSelected");
|
|
}
|
|
Ox.print("addToSelection")
|
|
that.triggerEvent("select", {
|
|
ids: $.map(self.selected, function(v, i) {
|
|
return self.ids[v];
|
|
})
|
|
});
|
|
}
|
|
}
|
|
|
|
function clear() {
|
|
$.each(self.requests, function(i, v) {
|
|
Ox.print("Ox.Request.cancel", v);
|
|
Ox.Request.cancel(v);
|
|
});
|
|
$.extend(self, {
|
|
$items: [],
|
|
$pages: [],
|
|
page: 0,
|
|
requests: []
|
|
});
|
|
}
|
|
|
|
function click(e) {
|
|
var $element = $(e.target), pos;
|
|
that.gainFocus();
|
|
while (!$element.hasClass("OxItem") && !$element.hasClass("OxPage")) {
|
|
$element = $element.parent();
|
|
}
|
|
if ($element.hasClass("OxItem")) {
|
|
Ox.print($element.attr("id"), $element.data("position"));
|
|
pos = $element.data("position");
|
|
if (e.shiftKey) {
|
|
addAllToSelection(pos);
|
|
} else if (e.metaKey) {
|
|
toggleSelection(pos);
|
|
} else {
|
|
select(pos);
|
|
}
|
|
} else {
|
|
selectNone();
|
|
}
|
|
}
|
|
|
|
function deselect(pos) {
|
|
if (isSelected(pos)) {
|
|
self.selected.splice(self.selected.indexOf(pos), 1);
|
|
if (!Ox.isUndefined(self.$items[pos])) {
|
|
self.$items[pos].removeClass("OxSelected");
|
|
}
|
|
that.triggerEvent("select", {
|
|
ids: $.map(self.selected, function(v, i) {
|
|
return self.ids[v];
|
|
})
|
|
});
|
|
}
|
|
}
|
|
|
|
function getHeight() {
|
|
return that.height() - (that.$content.width() > that.width() ? oxui.scrollbarSize : 0);
|
|
}
|
|
|
|
function getNext() {
|
|
var pos = -1;
|
|
if (self.selected.length) {
|
|
pos = Ox.max(self.selected) + 1;
|
|
if (pos == self.$items.length) {
|
|
pos = -1;
|
|
}
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
function getPage() {
|
|
return self.options.orientation == "horizontal"
|
|
? Math.floor(that.scrollLeft() / self.pageWidth)
|
|
: Math.floor(that.scrollTop() / self.pageHeight);
|
|
}
|
|
|
|
function getPositions() {
|
|
Ox.print("getPositions", $.map(self.selected, function(v, i) {
|
|
return self.ids[v];
|
|
}));
|
|
// fixme: optimize: send non-selected ids if more than half of the items are selected
|
|
if (self.selected.length /*&& self.selected.length < self.listLength*/) {
|
|
self.requests.push(self.options.request({
|
|
callback: getPositionsCallback,
|
|
ids: $.map(self.selected, function(v, i) {
|
|
return self.ids[v];
|
|
}),
|
|
sort: self.options.sort
|
|
}));
|
|
} else {
|
|
getPositionsCallback();
|
|
}
|
|
}
|
|
|
|
function getPositionsCallback(result) {
|
|
Ox.print("getPositionsCallback", result)
|
|
if (result) {
|
|
$.extend(self, {
|
|
ids: {},
|
|
selected: []
|
|
});
|
|
$.each(result.data.positions, function(id, pos) {
|
|
Ox.print("id", id, "pos", pos)
|
|
self.selected.push(pos);
|
|
});
|
|
}
|
|
load();
|
|
}
|
|
|
|
function getPrevious() {
|
|
var pos = -1;
|
|
if (self.selected.length) {
|
|
pos = Ox.min(self.selected) - 1;
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
function getWidth() {
|
|
return that.width() - (that.$content.height() > that.height() ? oxui.scrollbarSize : 0);
|
|
}
|
|
|
|
function invertSelection() {
|
|
$.each(Ox.range(self.listLength), function(i, v) {
|
|
toggleSelection(v);
|
|
});
|
|
}
|
|
|
|
function isSelected(pos) {
|
|
return self.selected.indexOf(pos) > -1;
|
|
}
|
|
|
|
function load() {
|
|
that.scrollTop(0);
|
|
that.$content.empty();
|
|
loadPages(self.page);
|
|
}
|
|
|
|
function loadPage(page, callback) {
|
|
Ox.print("loadPage", page)
|
|
if (page < 0 || page >= self.pages) {
|
|
!Ox.isUndefined(callback) && callback();
|
|
return;
|
|
}
|
|
var keys = $.inArray("id", self.options.keys) > -1 ? self.options.keys :
|
|
$.merge(self.options.keys, ["id"]),
|
|
offset = page * self.pageLength,
|
|
range = [offset, offset + (page < self.pages - 1 ?
|
|
self.pageLength : self.listLength % self.pageLength)];
|
|
if (Ox.isUndefined(self.$pages[page])) {
|
|
self.requests.push(self.options.request({
|
|
callback: function(result) {
|
|
self.$pages[page] = new Ox.ListPage();
|
|
if (self.options.type == "text") {
|
|
self.$pages[page].css({
|
|
top: (page * self.pageHeight) + "px"
|
|
});
|
|
} else {
|
|
self.$pages[page].css({
|
|
|
|
});
|
|
}
|
|
$.each(result.data.items, function(i, v) {
|
|
var pos = offset + i;
|
|
self.$items[pos] = new Ox.ListItem({
|
|
construct: self.options.construct,
|
|
data: v,
|
|
id: v[self.options.unique],
|
|
position: pos
|
|
});
|
|
self.ids[pos] = v[self.options.unique];
|
|
if (isSelected(pos)) {
|
|
self.$items[pos].addClass("OxSelected");
|
|
}
|
|
self.$items[pos].appendTo(self.$pages[page]);
|
|
});
|
|
if (self.options.type == "text" && page == 0) {
|
|
var height = that.height() - (that.width() < that.$content.width() ? oxui.scrollbarSize : 0),
|
|
visibleItems = Math.ceil(height / self.options.itemHeight);
|
|
if (result.data.items.length < visibleItems) {
|
|
self.$pages[page].height(height).css({
|
|
overflow: "hidden"
|
|
});
|
|
$.each(Ox.range(result.data.items.length, visibleItems), function(i, v) {
|
|
new Ox.ListItem({
|
|
construct: self.options.construct,
|
|
data: {},
|
|
id: "",
|
|
position: v
|
|
}).appendTo(self.$pages[page]);
|
|
});
|
|
}
|
|
}
|
|
self.$pages[page].appendTo(that.$content);
|
|
!Ox.isUndefined(callback) && callback();
|
|
},
|
|
keys: keys,
|
|
range: range,
|
|
sort: self.options.sort
|
|
}));
|
|
} else {
|
|
self.$pages[page].appendTo(that.$content);
|
|
}
|
|
}
|
|
|
|
function loadPages(page, callback) {
|
|
var counter = 0,
|
|
fn = function() {
|
|
counter++;
|
|
counter == 2 && !Ox.isUndefined(callback) && callback();
|
|
};
|
|
loadPage(page, function() {
|
|
loadPage(page - 1, fn);
|
|
loadPage(page + 1, fn);
|
|
});
|
|
}
|
|
|
|
function scroll() {
|
|
var page = self.page;
|
|
self.page = getPage();
|
|
if (self.page == page - 1) {
|
|
unloadPage(self.page + 2);
|
|
loadPage(self.page - 1);
|
|
} else if (self.page ==page + 1) {
|
|
unloadPage(self.page - 2);
|
|
loadPage(self.page + 1);
|
|
} else if (self.page == page - 2) {
|
|
unloadPage(self.page + 3);
|
|
unloadPage(self.page + 2);
|
|
loadPage(self.page);
|
|
loadPage(self.page - 1);
|
|
} else if (self.page == page + 2) {
|
|
unloadPage(self.page - 3);
|
|
unloadPage(self.page - 2);
|
|
loadPage(self.page);
|
|
loadPage(self.page + 1);
|
|
} else if (self.page != page) {
|
|
unloadPages(page);
|
|
loadPages(self.page);
|
|
}
|
|
}
|
|
|
|
function scrollPageDown() {
|
|
that.scrollBy(getHeight());
|
|
}
|
|
|
|
function scrollPageUp() {
|
|
that.scrollBy(-getHeight());
|
|
}
|
|
|
|
function scrollTo(pos) {
|
|
var positions = [], scroll, size;
|
|
if (self.options.orientation == "horizontal") {
|
|
|
|
} else if (self.options.orientation == "vertical") {
|
|
positions[0] = self.options.itemHeight * pos;
|
|
positions[1] = positions[0] + self.options.itemHeight;
|
|
scroll = that.scrollTop();
|
|
size = getHeight();
|
|
if (positions[0] < scroll) {
|
|
that.animate({
|
|
scrollTop: positions[0] + "px"
|
|
}, 0);
|
|
} else if (positions[1] > scroll + size) {
|
|
that.animate({
|
|
scrollTop: (positions[1] - size) + "px"
|
|
}, 0);
|
|
}
|
|
} else {
|
|
|
|
}
|
|
}
|
|
|
|
function scrollToFirst() {
|
|
that.scrollTop(0);
|
|
}
|
|
|
|
function scrollToLast() {
|
|
that.scrollTop(self.listHeight);
|
|
}
|
|
|
|
function select(pos) {
|
|
if (!isSelected(pos) || self.selected.length > 1) {
|
|
selectNone();
|
|
addToSelection(pos);
|
|
}
|
|
}
|
|
|
|
function selectAll() {
|
|
$.each(Ox.range(self.listLength), function(i, v) {
|
|
Ox.print("adding", v);
|
|
addToSelection(v);
|
|
});
|
|
}
|
|
|
|
function selectNext() {
|
|
var pos = getNext();
|
|
if (pos > -1) {
|
|
select(pos);
|
|
scrollTo(pos);
|
|
}
|
|
}
|
|
|
|
function selectNone() {
|
|
$.each(self.$items, function(i, v) {
|
|
deselect(i);
|
|
});
|
|
}
|
|
|
|
function selectPrevious() {
|
|
var pos = getPrevious();
|
|
if (pos > -1) {
|
|
select(pos);
|
|
scrollTo(pos);
|
|
}
|
|
}
|
|
|
|
function selectQuery(str) {
|
|
$.each(self.$items, function(i, v) {
|
|
if (Ox.toLatin(v.title).toUpperCase().indexOf(str) == 0) {
|
|
select(i);
|
|
scrollTo(i);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
function toggleSelection(pos) {
|
|
if (!isSelected(pos)) {
|
|
addToSelection(pos);
|
|
} else {
|
|
deselect(pos);
|
|
}
|
|
}
|
|
|
|
function unloadPage(page) {
|
|
if (page < 0 || page >= self.pages) {
|
|
return;
|
|
}
|
|
Ox.print("unloadPage", page)
|
|
Ox.print("self.$pages", self.$pages)
|
|
Ox.print(!Ox.isUndefined(self.$pages[page]))
|
|
!Ox.isUndefined(self.$pages[page]) && self.$pages[page].remove();
|
|
}
|
|
|
|
function unloadPages(page) {
|
|
unloadPage(page);
|
|
unloadPage(page - 1);
|
|
unloadPage(page + 1)
|
|
}
|
|
|
|
function updateQuery() {
|
|
clear();
|
|
self.requests.push(self.options.request({
|
|
callback: function(result) {
|
|
var keys = {};
|
|
that.triggerEvent("load", result.data);
|
|
$.extend(self, {
|
|
listHeight: result.data.items * self.options.itemHeight, // fixme: should be listSize
|
|
listLength: result.data.items,
|
|
pages: Math.ceil(result.data.items / self.pageLength),
|
|
pageWidth: self.options.orientation == "horizontal" ?
|
|
self.pageLength * self.options.itemWidth : 0,
|
|
pageHeight: self.options.orientation == "horizontal" ? 0 :
|
|
self.pageLength * self.options.itemHeight / self.options.rowLength
|
|
});
|
|
that.$content.css({
|
|
height: self.listHeight + "px"
|
|
});
|
|
getPositions();
|
|
}
|
|
}));
|
|
}
|
|
|
|
function updateSort() {
|
|
if (self.listLength > 1) {
|
|
clear();
|
|
getPositions();
|
|
}
|
|
}
|
|
|
|
self.onChange = function(key, value) {
|
|
Ox.print("list onChange", key, value);
|
|
if (key == "request") {
|
|
updateQuery();
|
|
}
|
|
};
|
|
|
|
that.clearCache = function() { // fixme: unused? make private?
|
|
self.$pages = [];
|
|
};
|
|
|
|
that.sort = function(key, operator) {
|
|
if (key != self.options.sort[0].key || operator != self.options.sort[0].operator) {
|
|
self.options.sort[0] = {
|
|
key: key,
|
|
operator: operator
|
|
}
|
|
that.triggerEvent("sort", self.options.sort[0]);
|
|
updateSort();
|
|
}
|
|
}
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
Ox.ListItem = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
construct: function() {},
|
|
data: {},
|
|
id: "",
|
|
position: 0
|
|
})
|
|
.options(options || {});
|
|
|
|
$.each(self.options.data, function(k, v) {
|
|
self.options.data[k] = $.isArray(v) ? v.join(", ") : v;
|
|
});
|
|
|
|
that.$element = self.options.construct(self.options.data)
|
|
.addClass("OxItem")
|
|
.attr({
|
|
id: self.options.id
|
|
})
|
|
.data("position", self.options.position);
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
Ox.ListPage = function(options, self) {
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.addClass("OxPage");
|
|
return that;
|
|
};
|
|
|
|
Ox.TextList = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
columns: [],
|
|
columnWidth: [40, 800],
|
|
id: "",
|
|
request: function() {}, // {sort, range, keys, callback}
|
|
sort: []
|
|
})
|
|
.options(options || {})
|
|
.addClass("OxTextList");
|
|
|
|
$.each(self.options.columns, function(i, v) { // fixme: can this go into a generic ox.js function?
|
|
if (Ox.isUndefined(v.unique)) {
|
|
v.unique = false;
|
|
}
|
|
if (Ox.isUndefined(v.visible)) {
|
|
v.visible = false;
|
|
}
|
|
if (v.unique) {
|
|
self.unique = v.id;
|
|
}
|
|
});
|
|
|
|
$.extend(self, {
|
|
columnPositions: [],
|
|
columnWidths: [],
|
|
itemHeight: 16,
|
|
page: 0,
|
|
pageLength: 100,
|
|
scrollLeft: 0,
|
|
selectedColumn: getColumnIndexById(self.options.sort[0].key),
|
|
visibleColumns: $.map(self.options.columns, function(v, i) {
|
|
return v.visible ? v : null;
|
|
})
|
|
});
|
|
$.extend(self, {
|
|
pageHeight: self.pageLength * self.itemHeight
|
|
});
|
|
|
|
// Head
|
|
|
|
that.$bar = new Ox.Bar({
|
|
orientation: "horizontal",
|
|
size: 16
|
|
}).appendTo(that);
|
|
that.$head = new Ox.Container()
|
|
.addClass("OxHead")
|
|
.appendTo(that.$bar);
|
|
that.$head.$content.addClass("OxTitles");
|
|
that.$titles = [];
|
|
$.each(self.visibleColumns, function(i, v) {
|
|
var $order, $resize, $left, $center, $right, timeout = 0;
|
|
self.columnWidths[i] = v.width;
|
|
that.$titles[i] = $("<div>")
|
|
.addClass("OxTitle OxColumn" + Ox.toTitleCase(v.id))
|
|
.css({
|
|
width: (v.width - 9) + "px",
|
|
textAlign: v.align
|
|
})
|
|
.html(v.title)
|
|
.mousedown(function(e) {
|
|
timeout = setTimeout(function() {
|
|
dragColumn(v.id, e);
|
|
timeout = 0;
|
|
}, 250);
|
|
})
|
|
.mouseup(function() {
|
|
if (timeout) {
|
|
clearTimeout(timeout);
|
|
timeout = 0;
|
|
clickColumn(v.id);
|
|
}
|
|
})
|
|
.appendTo(that.$head.$content.$element);
|
|
self.columnPositions[i] = Ox.sum(self.columnWidths) - self.columnWidths[i] / 2;
|
|
$order = $("<div>")
|
|
.addClass("OxOrder")
|
|
.html(oxui.symbols["triangle_" + (
|
|
v.operator === "" ? "up" : "down"
|
|
)])
|
|
.click(function() {
|
|
$(this).prev().trigger("click")
|
|
})
|
|
.appendTo(that.$head.$content.$element);
|
|
$resize = $("<div>")
|
|
.addClass("OxResize")
|
|
.mousedown(function(e) {
|
|
var startWidth = self.columnWidths[i],
|
|
startX = e.clientX;
|
|
$window.mousemove(function(e) {
|
|
var x = e.clientX,
|
|
width = Ox.limit(
|
|
startWidth - startX + x,
|
|
self.options.columnWidth[0],
|
|
self.options.columnWidth[1]
|
|
);
|
|
resizeColumn(v.id, width);
|
|
});
|
|
$window.mouseup(function() {
|
|
$window.unbind("mousemove");
|
|
$window.unbind("mouseup");
|
|
});
|
|
})
|
|
.dblclick(function() {
|
|
resizeColumn(v.id, v.width);
|
|
})
|
|
.appendTo(that.$head.$content.$element);
|
|
$left = $("<div>").addClass("OxLeft").appendTo($resize);
|
|
$center = $("<div>").addClass("OxCenter").appendTo($resize);
|
|
$right = $("<div>").addClass("OxRight").appendTo($resize);
|
|
});
|
|
that.$head.$content.css({
|
|
width: (Ox.sum(self.columnWidths) + 2) + "px"
|
|
});
|
|
toggleSelected(self.options.columns[self.selectedColumn].id);
|
|
that.$titles[getColumnPositionById(self.options.columns[self.selectedColumn].id)].css({
|
|
width: (self.options.columns[self.selectedColumn].width - 25) + "px"
|
|
});
|
|
that.$select = new Ox.Button({
|
|
style: "symbol",
|
|
type: "image",
|
|
value: "select"
|
|
}).appendTo(that.$bar.$element);
|
|
|
|
// Body
|
|
|
|
that.$body = new Ox.List({
|
|
construct: constructItem,
|
|
id: self.options.id,
|
|
itemHeight: 16,
|
|
itemWidth: getItemWidth(),
|
|
keys: $.map(self.visibleColumns, function(v, i) {
|
|
return v.id;
|
|
}),
|
|
orientation: "vertical",
|
|
request: self.options.request,
|
|
sort: self.options.sort,
|
|
type: "text",
|
|
unique: self.unique
|
|
})
|
|
.addClass("OxBody")
|
|
.scroll(function() {
|
|
var scrollLeft = $(this).scrollLeft();
|
|
if (scrollLeft != self.scrollLeft) {
|
|
self.scrollLeft = scrollLeft;
|
|
that.$head.scrollLeft(scrollLeft);
|
|
}
|
|
})
|
|
.appendTo(that);
|
|
that.$body.$content.css({
|
|
width: getItemWidth() + "px"
|
|
});
|
|
|
|
Ox.print("s.vC", self.visibleColumns)
|
|
|
|
function addColumn(id) {
|
|
|
|
}
|
|
|
|
function clickColumn(id) {
|
|
Ox.print("clickColumn", id);
|
|
var i = getColumnIndexById(id),
|
|
isSelected = self.options.sort[0].key == self.options.columns[i].id;
|
|
that.sort(
|
|
self.options.columns[i].id, isSelected ?
|
|
(self.options.sort[0].operator === "" ? "-" : "") :
|
|
self.options.columns[i].operator
|
|
);
|
|
}
|
|
|
|
function constructItem(data) {
|
|
var $item = $("<div>")
|
|
.css({
|
|
width: Math.max(Ox.sum(self.columnWidths), that.$element.width() - oxui.scrollbarSize) + "px"
|
|
});
|
|
$.each(self.visibleColumns, function(i, v) {
|
|
var $cell = $("<div>")
|
|
.addClass("OxCell OxColumn" + Ox.toTitleCase(v.id))
|
|
.css({
|
|
width: (self.columnWidths[i] - 9) + "px",
|
|
textAlign: v.align
|
|
})
|
|
.html(!$.isEmptyObject(data) ? data[v.id] : "")
|
|
.appendTo($item);
|
|
});
|
|
return $item;
|
|
}
|
|
|
|
function dragColumn(id, e) {
|
|
var startX = e.clientX,
|
|
startPos = getColumnPositionById(id),
|
|
pos = startPos,
|
|
stopPos = startPos,
|
|
positions = $.map(self.visibleColumns, function(v, i) {
|
|
return self.columnPositions[i] - self.columnPositions[startPos]
|
|
});
|
|
$(".OxColumn" + Ox.toTitleCase(id)).css({
|
|
opacity: 0.1
|
|
});
|
|
that.$titles[startPos].addClass("OxDrag").css({ // fixme: why does the class not work?
|
|
cursor: "move"
|
|
});
|
|
Ox.print("positions", positions)
|
|
$window.mousemove(function(e) {
|
|
var d = e.clientX - startX;
|
|
$.each(positions, function(i, v) {
|
|
if (d < 0 && d < v) {
|
|
stopPos = i;
|
|
return false;
|
|
} else if (d > 0 && d > v) {
|
|
stopPos = i;
|
|
}
|
|
});
|
|
if (stopPos != pos) {
|
|
pos = stopPos;
|
|
moveColumn(id, pos);
|
|
}
|
|
});
|
|
$window.mouseup(function() {
|
|
dropColumn(id, pos);
|
|
$window.unbind("mousemove");
|
|
$window.unbind("mouseup");
|
|
});
|
|
}
|
|
|
|
function dropColumn(id, pos) {
|
|
Ox.print("dropColumn", id, pos)
|
|
var startPos = getColumnPositionById(id),
|
|
stopPos = pos,
|
|
$title = that.$titles.splice(startPos, 1)[0],
|
|
column = self.visibleColumns.splice(startPos, 1)[0],
|
|
width = self.columnWidths.splice(startPos, 1)[0];
|
|
that.$titles.splice(stopPos, 0, $title);
|
|
self.visibleColumns.splice(stopPos, 0, column);
|
|
self.columnWidths.splice(stopPos, 0, width);
|
|
Ox.print("s.vC", self.visibleColumns)
|
|
$(".OxColumn" + Ox.toTitleCase(id)).css({
|
|
opacity: 1
|
|
});
|
|
that.$titles[stopPos].removeClass("OxDrag").css({
|
|
cursor: "pointer"
|
|
});
|
|
}
|
|
|
|
function getColumnIndexById(id) {
|
|
var pos = -1;
|
|
$.each(self.options.columns, function(i, v) {
|
|
if (v.id == id) {
|
|
pos = i;
|
|
return false;
|
|
}
|
|
});
|
|
return pos;
|
|
}
|
|
|
|
function getColumnPositionById(id) {
|
|
var pos = -1;
|
|
$.each(self.visibleColumns, function(i, v) {
|
|
if (v.id == id) {
|
|
pos = i;
|
|
return false;
|
|
}
|
|
});
|
|
return pos;
|
|
}
|
|
|
|
function getItemWidth() {
|
|
return Ox.sum(self.columnWidths)
|
|
return Math.max(Ox.sum(self.columnWidths), that.$element.width() - oxui.scrollbarSize);
|
|
}
|
|
|
|
function moveColumn(id, pos) {
|
|
Ox.print("moveColumn", id, pos)
|
|
var startPos = getColumnPositionById(id),
|
|
stopPos = pos,
|
|
startClassName = ".OxColumn" + Ox.toTitleCase(id),
|
|
stopClassName = ".OxColumn" + Ox.toTitleCase(self.visibleColumns[stopPos].id),
|
|
$column = $(".OxTitle" + startClassName),
|
|
$order = $column.next(),
|
|
$resize = $order.next();
|
|
$column.detach().insertBefore($(".OxTitle" + stopClassName));
|
|
$order.detach().insertAfter($column);
|
|
$resize.detach().insertAfter($order);
|
|
$.each(that.$body.find(".OxItem"), function(i, v) {
|
|
var $v = $(v);
|
|
$v.children(startClassName).detach().insertBefore($v.children(stopClassName));
|
|
});
|
|
}
|
|
|
|
function removeColumn(id) {
|
|
|
|
}
|
|
|
|
function resize() {
|
|
|
|
}
|
|
|
|
function resizeColumn(id, width) {
|
|
var i = getColumnIndexById(id),
|
|
pos = getColumnPositionById(id);
|
|
self.columnWidths[pos] = width;
|
|
that.$head.$content.css({
|
|
width: (Ox.sum(self.columnWidths) + 2) + "px"
|
|
});
|
|
that.$titles[pos].css({
|
|
width: (width - 9 - (i == self.selectedColumn ? 16 : 0)) + "px"
|
|
});
|
|
that.$body.$content.find(".OxItem").css({ // fixme: can we avoid this lookup?
|
|
width: getItemWidth() + "px"
|
|
});
|
|
that.$body.$content.css({
|
|
width: getItemWidth() + "px" // fixme: check if scrollbar visible, and listen to resize/toggle event
|
|
});
|
|
$(".OxCell.OxColumn" + Ox.toTitleCase(self.options.columns[i].id)).css({
|
|
width: (width - 9) + "px"
|
|
});
|
|
that.$body.clearCache();
|
|
}
|
|
|
|
function toggleSelected(id) {
|
|
var pos = getColumnPositionById(id);
|
|
if (pos > -1) {
|
|
updateOrder(id);
|
|
pos > 0 && that.$titles[pos].prev().children().eq(2).toggleClass("OxSelected");
|
|
that.$titles[pos].toggleClass("OxSelected");
|
|
that.$titles[pos].next().toggleClass("OxSelected");
|
|
that.$titles[pos].next().next().children().eq(0).toggleClass("OxSelected");
|
|
that.$titles[pos].css({
|
|
width: (
|
|
that.$titles[pos].width() + (that.$titles[pos].hasClass("OxSelected") ? -16 : 16)
|
|
) + "px"
|
|
});
|
|
}
|
|
}
|
|
|
|
function updateOrder(id) {
|
|
var pos = getColumnPositionById(id);
|
|
Ox.print(id, pos)
|
|
that.$titles[pos].next().html(oxui.symbols[
|
|
"triangle_" + (self.options.sort[0].operator === "" ? "up" : "down")
|
|
]);
|
|
}
|
|
|
|
self.onChange = function(key, value) {
|
|
if (key == "request") {
|
|
that.$body.options(key, value);
|
|
}
|
|
};
|
|
|
|
that.resizeColumn = function(id, width) {
|
|
resizeColumn(id, width);
|
|
return that;
|
|
}
|
|
|
|
that.sort = function(key, operator) {
|
|
var isSelected = key == self.options.sort[0].key;
|
|
self.options.sort = [
|
|
{
|
|
key: key,
|
|
operator: operator
|
|
}
|
|
];
|
|
if (isSelected) {
|
|
updateOrder(self.options.columns[self.selectedColumn].id);
|
|
} else {
|
|
toggleSelected(self.options.columns[self.selectedColumn].id);
|
|
self.selectedColumn = getColumnIndexById(key);
|
|
toggleSelected(self.options.columns[self.selectedColumn].id);
|
|
}
|
|
that.$body.sort(self.options.sort[0].key, self.options.sort[0].operator);
|
|
return that;
|
|
};
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
/*
|
|
============================================================================
|
|
Menus
|
|
============================================================================
|
|
*/
|
|
|
|
Ox.MainMenu = function(options, self) {
|
|
|
|
/* options:
|
|
* extras
|
|
* menus
|
|
* size
|
|
*/
|
|
|
|
var self = self || {},
|
|
that = new Ox.Bar({}, self)
|
|
.defaults({
|
|
extras: [],
|
|
menus: [],
|
|
size: "medium"
|
|
})
|
|
.options(options || {})
|
|
.addClass("OxMainMenu Ox" + Ox.toTitleCase(self.options.size)) // fixme: bar should accept small/medium/large ... like toolbar
|
|
.click(click)
|
|
.mousemove(mousemove);
|
|
|
|
self.focused = false;
|
|
self.selected = -1;
|
|
that.menus = [];
|
|
that.titles = [];
|
|
that.layer = $("<div>").addClass("OxLayer");
|
|
|
|
$.each(self.options.menus, function(position, menu) {
|
|
that.titles[position] = $("<div>")
|
|
.addClass("OxTitle")
|
|
.html(menu.title)
|
|
.data("position", position)
|
|
.appendTo(that.$element);
|
|
that.menus[position] = new Ox.Menu($.extend(menu, {
|
|
element: that.titles[position],
|
|
mainmenu: that,
|
|
size: self.options.size
|
|
}));
|
|
that.bindEvent("hide_" + that.menus[position].options("id"), onHideMenu);
|
|
});
|
|
|
|
if (self.options.extras.length) {
|
|
that.extras = $("<div>")
|
|
.addClass("OxExtras")
|
|
.appendTo(that.$element);
|
|
$.each(self.options.extras, function(position, extra) {
|
|
extra.css({
|
|
float: "left" // fixme: need class!
|
|
}).appendTo(that.extras);
|
|
});
|
|
}
|
|
|
|
function click(event) {
|
|
var $target = $(event.target),
|
|
position = typeof $target.data("position") != "undefined" ?
|
|
$target.data("position") : -1;
|
|
clickTitle(position);
|
|
}
|
|
|
|
function clickTitle(position) {
|
|
var selected = self.selected;
|
|
if (self.selected > -1) {
|
|
that.menus[self.selected].hideMenu();
|
|
}
|
|
if (position > -1) {
|
|
if (position != selected) {
|
|
self.focused = true;
|
|
self.selected = position;
|
|
that.titles[self.selected].addClass("OxSelected");
|
|
that.menus[self.selected].showMenu();
|
|
}
|
|
}
|
|
}
|
|
|
|
function getMenuById(id) {
|
|
var menu = null;
|
|
$.each(that.menus, function(i, v) {
|
|
if (v.options("id") == id) {
|
|
menu = v;
|
|
return false;
|
|
}
|
|
});
|
|
return menu;
|
|
}
|
|
|
|
function mousemove(event) {
|
|
var $target = $(event.target),
|
|
focused,
|
|
position = typeof $target.data("position") != "undefined" ?
|
|
$target.data("position") : -1;
|
|
if (self.focused && position != self.selected) {
|
|
if (position > -1) {
|
|
clickTitle(position);
|
|
} else {
|
|
focused = self.focused;
|
|
that.menus[self.selected].hideMenu();
|
|
self.focused = focused;
|
|
}
|
|
}
|
|
}
|
|
|
|
function onHideMenu() {
|
|
if (self.selected > -1) {
|
|
that.titles[self.selected].removeClass("OxSelected");
|
|
self.selected = -1;
|
|
}
|
|
self.focused = false;
|
|
}
|
|
|
|
self.onChange = function(key, value) {
|
|
|
|
};
|
|
|
|
that.addMenuAfter = function(id) {
|
|
|
|
};
|
|
|
|
that.addMenuBefore = function(id) {
|
|
|
|
};
|
|
|
|
that.checkItem = function(id) {
|
|
that.getItem(id).options({
|
|
checked: true
|
|
});
|
|
};
|
|
|
|
that.disableItem = function(id) {
|
|
that.getItem(id).options({
|
|
disabled: true
|
|
});
|
|
};
|
|
|
|
that.enableItem = function(id) {
|
|
that.getItem(id).options({
|
|
disabled: false
|
|
});
|
|
};
|
|
|
|
that.getItem = function(id) {
|
|
var ids = id.split("_"),
|
|
item;
|
|
if (ids.length == 1) {
|
|
$.each(that.menus, function(i, menu) {
|
|
item = menu.getItem(id);
|
|
return !item;
|
|
});
|
|
} else {
|
|
item = getMenuById(ids.shift()).getItem(ids.join("_"));
|
|
}
|
|
return item;
|
|
};
|
|
|
|
that.removeMenu = function() {
|
|
|
|
};
|
|
|
|
that.selectNextMenu = function() {
|
|
if (self.selected < self.options.menus.length - 1) {
|
|
clickTitle(self.selected + 1);
|
|
}
|
|
};
|
|
|
|
that.selectPreviousMenu = function() {
|
|
if (self.selected) {
|
|
clickTitle(self.selected - 1);
|
|
}
|
|
};
|
|
|
|
that.uncheckItem = function(id) {
|
|
that.getItem(id).options({
|
|
checked: false
|
|
});
|
|
};
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
Ox.Menu = function(options, self) {
|
|
|
|
/*
|
|
|
|
options:
|
|
element the element the menu is attached to
|
|
id the menu id
|
|
items array of menu items
|
|
mainmenu the main menu this menu is part of, if any
|
|
offset offset of the menu, in px
|
|
parent the supermenu, if any
|
|
selected the position of the selected item
|
|
side open to "bottom" or "right"
|
|
size "large", "medium" or "small"
|
|
|
|
methods:
|
|
|
|
events:
|
|
change_groupId {id, value} checked item of a group has changed
|
|
click_itemId item not belonging to a group was clicked
|
|
click_menuId {id, value} item not belonging to a group was clicked
|
|
deselect_menuId {id, value} item was deselected not needed, not implemented
|
|
hide_menuId menu was hidden
|
|
select_menuId {id, value} item was selected not needed, not implemented
|
|
|
|
*/
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
element: null,
|
|
id: "",
|
|
items: [],
|
|
mainmenu: null,
|
|
offset: {
|
|
left: 0,
|
|
top: 0
|
|
},
|
|
parent: null,
|
|
selected: -1,
|
|
side: "bottom",
|
|
size: "medium",
|
|
})
|
|
.options(options)
|
|
.addClass(
|
|
"OxMenu Ox" + Ox.toTitleCase(self.options.side) +
|
|
" Ox" + Ox.toTitleCase(self.options.size)
|
|
)
|
|
.click(click)
|
|
.mouseenter(mouseenter)
|
|
.mouseleave(mouseleave)
|
|
.mousemove(mousemove),
|
|
itemHeight = self.options.size == "small" ? 12 : (self.options.size == "medium" ? 16 : 20),
|
|
// menuHeight,
|
|
scrollSpeed = 1,
|
|
$item; // fixme: used?
|
|
// fixme: attach all private vars to self?
|
|
|
|
self.keyboardEvents = {
|
|
key_up: selectPreviousItem,
|
|
key_down: selectNextItem,
|
|
key_left: selectSupermenu,
|
|
key_right: selectSubmenu,
|
|
key_escape: hideMenu,
|
|
key_enter: clickSelectedItem
|
|
};
|
|
|
|
// construct
|
|
that.items = [];
|
|
that.submenus = {};
|
|
that.$scrollbars = [];
|
|
that.$top = $("<div>")
|
|
.addClass("OxTop")
|
|
.appendTo(that.$element);
|
|
that.$scrollbars.up = constructScrollbar("up")
|
|
.appendTo(that.$element);
|
|
that.$container = $("<div>")
|
|
.addClass("OxContainer")
|
|
.appendTo(that.$element);
|
|
that.$content = $("<table>")
|
|
.addClass("OxContent")
|
|
.appendTo(that.$container);
|
|
constructItems(self.options.items);
|
|
that.$scrollbars.down = constructScrollbar("down")
|
|
.appendTo(that.$element);
|
|
that.$bottom = $("<div>")
|
|
.addClass("OxBottom")
|
|
.appendTo(that.$element);
|
|
that.$layer = $("<div>")
|
|
.addClass(self.options.mainmenu ? "OxMainMenuLayer" : "OxLayer");
|
|
|
|
function click(event) {
|
|
var item,
|
|
position,
|
|
$target = $(event.target);
|
|
if ($target.is(".OxCell")) {
|
|
position = $target.parent().data("position");
|
|
item = that.items[position];
|
|
if (!item.options("disabled")) {
|
|
clickItem(position);
|
|
} else {
|
|
that.hideMenu();
|
|
}
|
|
} else {
|
|
that.hideMenu();
|
|
}
|
|
}
|
|
|
|
function clickItem(position) {
|
|
var item = that.items[position];
|
|
if (!item.options("items").length) {
|
|
if (that.options("parent")) {
|
|
Ox.print("t.o.p", that.options("parent"))
|
|
that.options("parent").hideMenu().triggerEvent("click");
|
|
}
|
|
if (item.options("checked") !== null && (!item.options("group") || !item.options("checked"))) {
|
|
item.options({
|
|
checked: !item.options("checked")
|
|
});
|
|
Ox.Event.trigger("change_" + item.options("group"), {
|
|
id: item.options("id"),
|
|
value: item.options("title")[0] // fixme: value or title?
|
|
});
|
|
} else {
|
|
Ox.Event.trigger("click_" + self.options.id, {
|
|
id: item.options("id"),
|
|
title: item.options("title")[0]
|
|
});
|
|
Ox.Event.trigger("click_" + item.options("id"));
|
|
}
|
|
if (item.options("title").length == 2) {
|
|
item.toggleTitle();
|
|
}
|
|
}
|
|
that.hideMenu();
|
|
}
|
|
|
|
function clickSelectedItem() {
|
|
// called on key.enter
|
|
if (self.options.selected > -1) {
|
|
clickItem(self.options.selected);
|
|
} else {
|
|
that.hideMenu();
|
|
}
|
|
}
|
|
|
|
function constructItems(items) {
|
|
that.items = [];
|
|
that.$content.empty();
|
|
scrollMenuUp();
|
|
$.each(items, function(i, item) {
|
|
var position;
|
|
if (item.id) {
|
|
that.items.push(new Ox.MenuItem($.extend(item, {
|
|
menu: that,
|
|
position: position = that.items.length
|
|
})).data("position", position).appendTo(that.$content)); // fixme: jquery bug when passing {position: position}? does not return the object?;
|
|
if (item.items) {
|
|
that.submenus[item.id] = new Ox.Menu({
|
|
element: that.items[position],
|
|
id: Ox.toCamelCase(self.options.id + "/" + item.id),
|
|
items: item.items,
|
|
mainmenu: self.options.mainmenu,
|
|
offset: {
|
|
left: 0,
|
|
top: -4
|
|
},
|
|
parent: that,
|
|
side: "right",
|
|
size: self.options.size,
|
|
});
|
|
}
|
|
} else {
|
|
that.$content.append(constructSpace());
|
|
that.$content.append(constructLine());
|
|
that.$content.append(constructSpace());
|
|
}
|
|
});
|
|
if (!that.is(":hidden")) {
|
|
that.hideMenu();
|
|
that.showMenu();
|
|
}
|
|
}
|
|
|
|
function constructLine() {
|
|
return $("<tr>").append(
|
|
$("<td>", {
|
|
"class": "OxLine",
|
|
colspan: 5
|
|
})
|
|
);
|
|
}
|
|
|
|
function constructScrollbar(direction) {
|
|
var interval,
|
|
speed = direction == "up" ? -1 : 1;
|
|
return $("<div/>", {
|
|
"class": "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(speed);
|
|
interval = setInterval(function() {
|
|
scrollMenu(speed);
|
|
}, 100);
|
|
},
|
|
mouseleave: function() {
|
|
$(this).removeClass("OxSelected");
|
|
clearInterval(interval);
|
|
},
|
|
mouseup: function() {
|
|
scrollSpeed = 1;
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
function constructSpace() {
|
|
return $("<tr>").append(
|
|
$("<td>", {
|
|
"class": "OxSpace",
|
|
colspan: 5
|
|
})
|
|
);
|
|
}
|
|
|
|
function getElement(id) {
|
|
// fixme: needed?
|
|
return $("#" + Ox.toCamelCase(options.id + "/" + id));
|
|
}
|
|
|
|
function hideMenu() {
|
|
// called on key_escape
|
|
that.hideMenu();
|
|
}
|
|
|
|
function isFirstEnabledItem() {
|
|
var ret = true;
|
|
$.each(that.items, function(i, item) {
|
|
if (i < self.options.selected && !item.options("disabled")) {
|
|
return ret = false;
|
|
}
|
|
});
|
|
return ret;
|
|
}
|
|
|
|
function isLastEnabledItem() {
|
|
var ret = true;
|
|
$.each(that.items, function(i, item) {
|
|
if (i > self.options.selected && !item.options("disabled")) {
|
|
return ret = false;
|
|
}
|
|
});
|
|
return ret;
|
|
}
|
|
|
|
function mouseenter() {
|
|
that.gainFocus();
|
|
}
|
|
|
|
function mouseleave() {
|
|
if (self.options.selected > -1 && !that.items[self.options.selected].options("items").length) {
|
|
selectItem(-1);
|
|
}
|
|
}
|
|
|
|
function mousemove(event) {
|
|
var item,
|
|
position,
|
|
$target = $(event.target);
|
|
if ($target.is(".OxCell")) {
|
|
position = $target.parent().data("position");
|
|
item = that.items[position];
|
|
if (!item.options("disabled") && position != self.options.selected) {
|
|
selectItem(position);
|
|
}
|
|
} else {
|
|
mouseleave();
|
|
}
|
|
}
|
|
|
|
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.height(containerHeight + itemHeight);
|
|
that.items[that.items.length - 1].trigger("mouseover");
|
|
} else if (top >= max - itemHeight) {
|
|
top = max;
|
|
that.$scrollbars.up.hide().trigger("mouseleave");
|
|
that.$container.height(containerHeight + itemHeight);
|
|
that.items[0].trigger("mouseover");
|
|
}
|
|
that.$content.css({
|
|
top: top + "px"
|
|
});
|
|
}
|
|
|
|
function scrollMenuUp() {
|
|
if (that.$scrollbars.up.is(":visible")) {
|
|
that.$content.css({
|
|
top: "0px"
|
|
});
|
|
that.$scrollbars.up.hide();
|
|
if (that.$scrollbars.down.is(":hidden")) {
|
|
that.$scrollbars.down.show();
|
|
} else {
|
|
that.$container.height(that.$container.height() + itemHeight);
|
|
}
|
|
}
|
|
}
|
|
|
|
function selectItem(position) {
|
|
var item;
|
|
if (self.options.selected > -1) {
|
|
item = that.items[self.options.selected]
|
|
item.removeClass("OxSelected");
|
|
}
|
|
if (position > -1) {
|
|
item = that.items[position];
|
|
$.each(that.submenus, function(id, submenu) {
|
|
if (!submenu.is(":hidden")) {
|
|
submenu.hideMenu();
|
|
return false;
|
|
}
|
|
});
|
|
item.options("items").length && that.submenus[item.options("id")].showMenu(); // fixme: do we want to switch to this style?
|
|
item.addClass("OxSelected");
|
|
}
|
|
self.options.selected = position;
|
|
}
|
|
|
|
function selectNextItem() {
|
|
var offset,
|
|
selected = self.options.selected;
|
|
Ox.print("sNI", selected)
|
|
if (!isLastEnabledItem()) {
|
|
if (selected == -1) {
|
|
scrollMenuUp();
|
|
} else {
|
|
that.items[selected].removeClass("OxSelected");
|
|
}
|
|
do {
|
|
selected++;
|
|
} while (that.items[selected].options("disabled"))
|
|
selectItem(selected);
|
|
offset = that.items[selected].offset().top + itemHeight -
|
|
that.$container.offset().top - that.$container.height();
|
|
if (offset > 0) {
|
|
if (that.$scrollbars.up.is(":hidden")) {
|
|
that.$scrollbars.up.show();
|
|
that.$container.height(that.$container.height() - itemHeight);
|
|
offset += itemHeight;
|
|
}
|
|
if (selected == that.items.length - 1) {
|
|
that.$scrollbars.down.hide();
|
|
that.$container.height(that.$container.height() + itemHeight);
|
|
} else {
|
|
that.$content.css({
|
|
top: ((parseInt(that.$content.css("top")) || 0) - offset) + "px"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function selectPreviousItem() {
|
|
var offset,
|
|
selected = self.options.selected;
|
|
Ox.print("sPI", selected)
|
|
if (selected > - 1) {
|
|
if (!isFirstEnabledItem()) {
|
|
that.items[selected].removeClass("OxSelected");
|
|
do {
|
|
selected--;
|
|
} while (that.items[selected].options("disabled"))
|
|
selectItem(selected);
|
|
}
|
|
offset = that.items[selected].offset().top - that.$container.offset().top;
|
|
if (offset < 0) {
|
|
if (that.$scrollbars.down.is(":hidden")) {
|
|
that.$scrollbars.down.show();
|
|
that.$container.height(that.$container.height() - itemHeight);
|
|
}
|
|
if (selected == 0) {
|
|
that.$scrollbars.up.hide();
|
|
that.$container.height(that.$container.height() + itemHeight);
|
|
}
|
|
that.$content.css({
|
|
top: ((parseInt(that.$content.css("top")) || 0) - offset) + "px"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function selectSubmenu() {
|
|
Ox.print("selectSubmenu", self.options.selected)
|
|
if (self.options.selected > -1) {
|
|
var submenu = that.submenus[that.items[self.options.selected].options("id")];
|
|
if (submenu && submenu.hasEnabledItems()) {
|
|
submenu.gainFocus();
|
|
submenu.selectFirstItem();
|
|
} else if (self.options.mainmenu) {
|
|
self.options.mainmenu.selectNextMenu();
|
|
}
|
|
} else if (self.options.mainmenu) {
|
|
self.options.mainmenu.selectNextMenu();
|
|
}
|
|
}
|
|
|
|
function selectSupermenu() {
|
|
Ox.print("selectSupermenu", self.options.selected)
|
|
if (self.options.parent) {
|
|
that.items[self.options.selected].trigger("mouseleave");
|
|
self.options.parent.gainFocus();
|
|
} else if (self.options.mainmenu) {
|
|
self.options.mainmenu.selectPreviousMenu();
|
|
}
|
|
}
|
|
|
|
self.onChange = function(key, value) {
|
|
if (key == "items") {
|
|
constructItems(value);
|
|
} else if (key == "selected") {
|
|
selectItem(value);
|
|
}
|
|
}
|
|
|
|
that.addItem = function(item, position) {
|
|
|
|
};
|
|
|
|
that.addItemAfter = function(item, id) {
|
|
|
|
};
|
|
|
|
that.addItemBefore = function(item, id) {
|
|
|
|
};
|
|
|
|
that.checkItem = function(id) {
|
|
that.getItem(id).options({
|
|
checked: true
|
|
});
|
|
};
|
|
|
|
that.getItem = function(id) {
|
|
var ids = id.split("_"),
|
|
item;
|
|
if (ids.length == 1) {
|
|
$.each(that.items, function(i, v) {
|
|
if (v.options("id") == id) {
|
|
item = v;
|
|
return false;
|
|
}
|
|
});
|
|
if (!item) {
|
|
$.each(that.submenus, function(k, submenu) {
|
|
item = submenu.getItem(id);
|
|
return !item;
|
|
});
|
|
}
|
|
} else {
|
|
item = that.submenus[ids.shift()].getItem(ids.join("_"));
|
|
}
|
|
return item;
|
|
};
|
|
|
|
that.hasEnabledItems = function() {
|
|
var ret = false;
|
|
$.each(that.items, function(i, item) {
|
|
if (!item.options("disabled")) {
|
|
return ret = true;
|
|
}
|
|
});
|
|
return ret;
|
|
};
|
|
|
|
that.hideMenu = function() {
|
|
if (that.is(":hidden")) {
|
|
return;
|
|
}
|
|
$.each(that.submenus, function(i, submenu) {
|
|
if (submenu.is(":visible")) {
|
|
submenu.hideMenu();
|
|
return false;
|
|
}
|
|
});
|
|
selectItem(-1);
|
|
scrollMenuUp();
|
|
that.$scrollbars.up.is(":visible") && that.$scrollbars.up.hide();
|
|
that.$scrollbars.down.is(":visible") && that.$scrollbars.down.hide();
|
|
//that.$scrollbars.down.hide();
|
|
if (self.options.parent) {
|
|
self.options.element.removeClass("OxSelected");
|
|
}
|
|
that.hide()
|
|
.loseFocus()
|
|
.unbindEvent(self.keyboardEvents)
|
|
.triggerEvent("hide");
|
|
that.$layer.hide();
|
|
$document.unbind("click", click);
|
|
return that;
|
|
//that.triggerEvent("hide");
|
|
};
|
|
|
|
that.removeItem = function() {
|
|
|
|
};
|
|
|
|
that.selectFirstItem = function() {
|
|
selectNextItem();
|
|
};
|
|
|
|
that.showMenu = function() {
|
|
if (!that.is(":hidden")) {
|
|
return;
|
|
}
|
|
if (!self.options.parent && !that.$layer.parent().length) {
|
|
that.$layer.appendTo($body);
|
|
}
|
|
that.parent().length || that.appendTo($body);
|
|
that.css({
|
|
left: "-1000px",
|
|
top: "-1000px",
|
|
}).show();
|
|
var offset = self.options.element.offset(),
|
|
width = self.options.element.outerWidth(),
|
|
height = self.options.element.outerHeight(),
|
|
left = offset.left + self.options.offset.left + (self.options.side == "bottom" ? 0 : width),
|
|
top = offset.top + self.options.offset.top + (self.options.side == "bottom" ? height : 0),
|
|
menuHeight = that.$content.outerHeight(); // fixme: why is outerHeight 0 when hidden?
|
|
menuMaxHeight = Math.floor($window.height() - top - 16);
|
|
if (self.options.parent) {
|
|
if (menuHeight > menuMaxHeight) {
|
|
top = Ox.limit(top - menuHeight + menuMaxHeight, self.options.parent.offset().top, top);
|
|
menuMaxHeight = Math.floor($window.height() - top - 16);
|
|
}
|
|
}
|
|
that.css({
|
|
left: left + "px",
|
|
top: top + "px"
|
|
});
|
|
if (menuHeight > menuMaxHeight) {
|
|
that.$container.height(menuMaxHeight - itemHeight - 8); // margin
|
|
that.$scrollbars.down.show();
|
|
} else {
|
|
that.$container.height(menuHeight);
|
|
}
|
|
!self.options.parent && that.gainFocus();
|
|
that.bindEvent(self.keyboardEvents);
|
|
setTimeout(function() {
|
|
$document.bind("click", click);
|
|
}, 100);
|
|
return that;
|
|
//that.triggerEvent("show");
|
|
};
|
|
|
|
that.toggleMenu = function() {
|
|
that.is(":hidden") ? that.showMenu() : that.hideMenu();
|
|
};
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
Ox.MenuItem = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element("tr", self)
|
|
.defaults({
|
|
bind: [],
|
|
checked: null,
|
|
disabled: false,
|
|
group: "",
|
|
icon: "",
|
|
id: "",
|
|
items: [],
|
|
keyboard: "",
|
|
menu: null, // fixme: is passing the menu to 100s of menu items really memory-neutral?
|
|
position: 0,
|
|
title: [],
|
|
})
|
|
.options($.extend(options, {
|
|
keyboard: parseKeyboard(options.keyboard || self.defaults.keyboard),
|
|
title: Ox.makeArray(options.title || self.defaults.title)
|
|
}))
|
|
.addClass("OxItem" + (self.options.disabled ? " OxDisabled" : ""))
|
|
.attr({
|
|
id: Ox.toCamelCase(self.options.menu.options("id") + "/" + self.options.id)
|
|
})
|
|
.data("group", self.options.group); // fixme: why?
|
|
|
|
// construct
|
|
that.append(
|
|
that.$status = $("<td>", {
|
|
"class": "OxCell OxStatus",
|
|
html: self.options.checked ? oxui.symbols.check : ""
|
|
})
|
|
)
|
|
.append(
|
|
that.$icon = $("<td>", {
|
|
"class": "OxCell OxIcon"
|
|
})
|
|
.append(self.options.icon ?
|
|
$("<img>", {
|
|
src: self.options.icon
|
|
}) : null
|
|
)
|
|
)
|
|
.append(
|
|
that.$title = $("<td>", {
|
|
"class": "OxCell OxTitle",
|
|
html: self.options.title[0]
|
|
})
|
|
)
|
|
.append(
|
|
$("<td>", {
|
|
"class": "OxCell OxModifiers",
|
|
html: $.map(self.options.keyboard.modifiers, function(modifier) {
|
|
return oxui.symbols[modifier];
|
|
}).join("")
|
|
})
|
|
)
|
|
.append(
|
|
$("<td>", {
|
|
"class": "OxCell Ox" + (self.options.items.length ? "Submenu" : "Key"),
|
|
html: self.options.items.length ? oxui.symbols.triangle_right :
|
|
oxui.symbols[self.options.keyboard.key] ||
|
|
self.options.keyboard.key.toUpperCase()
|
|
})
|
|
);
|
|
|
|
function parseKeyboard(str) {
|
|
var modifiers = str.split(" "),
|
|
key = modifiers.pop();
|
|
return {
|
|
modifiers: modifiers,
|
|
key: key
|
|
};
|
|
}
|
|
|
|
self.onChange = function(key, value) {
|
|
if (key == "checked") {
|
|
if (value && self.options.group) {
|
|
$.each(self.options.menu.items, function(i, item) {
|
|
if (
|
|
item.options("id") != self.options.id &&
|
|
item.options("group") == self.options.group &&
|
|
item.options("checked")
|
|
) {
|
|
item.options({
|
|
checked: false
|
|
});
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
that.$status.html(value ? oxui.symbols.check : "")
|
|
} else if (key == "disabled") {
|
|
that.toggleClass("OxDisabled"); // fixme: this will only work if onChange is only invoked on actual change
|
|
} else if (key == "title") {
|
|
|
|
}
|
|
}
|
|
|
|
that.toggle = function() {
|
|
// toggle id and title
|
|
};
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
/*
|
|
============================================================================
|
|
Panels
|
|
============================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.CollapsePanel
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.CollapsePanel = function(options, self) {
|
|
var self = self || {},
|
|
that = new Ox.Panel({}, self)
|
|
.defaults({
|
|
collapsed: false,
|
|
size: 20,
|
|
title: ""
|
|
})
|
|
.options(options)
|
|
.addClass("OxCollapsePanel"),
|
|
value = self.options.collapsed ?
|
|
["expand", "collapsed"] : ["collapse", "expand"],
|
|
$titlebar = new Ox.Bar({
|
|
orientation: "horizontal",
|
|
size: self.options.size,
|
|
})
|
|
.dblclick(dblclickTitlebar)
|
|
.appendTo(that),
|
|
$switch = new Ox.Button({
|
|
style: "symbol",
|
|
type: "image",
|
|
value: value,
|
|
})
|
|
.click(toggleCollapsed)
|
|
.appendTo($titlebar),
|
|
$title = new Ox.Element()
|
|
.addClass("OxTitle")
|
|
.html(self.options.title/*.toUpperCase()*/)
|
|
.appendTo($titlebar);
|
|
that.$content = new Ox.Element()
|
|
.addClass("OxContent")
|
|
.appendTo(that);
|
|
// fixme: doesn't work, content still empty
|
|
// need to hide it if collapsed
|
|
if (self.options.collapsed) {
|
|
that.$content.css({
|
|
marginTop: -that.$content.height() + "px"
|
|
});
|
|
}
|
|
function dblclickTitlebar(e) {
|
|
if (!$(e.target).hasClass("OxButton")) {
|
|
toggleCollapsed();
|
|
}
|
|
}
|
|
function toggleCollapsed() {
|
|
that.options({
|
|
collapsed: !self.options.collapsed
|
|
});
|
|
var top = self.options.collapsed ?
|
|
-that.$content.height() : 0;
|
|
that.$content.animate({
|
|
marginTop: top + "px"
|
|
}, 200);
|
|
}
|
|
self.onChange = function(option, value) {
|
|
if (option == "collapsed") {
|
|
$switch.options({
|
|
value: value ? "expand" : "collapse"
|
|
});
|
|
} else if (option == "title") {
|
|
$title.html(self.options.title);
|
|
}
|
|
};
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Panel
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.Panel = function(options, self) {
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.addClass("OxPanel");
|
|
return that;
|
|
};
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.SplitPanel
|
|
options:
|
|
orientation: "" "horizontal" or "vertical"
|
|
elements: [{
|
|
element, Ox Element
|
|
size: 0, size in px
|
|
resizable: false resizable or not
|
|
}]
|
|
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.SplitPanel = function(options, self) {
|
|
|
|
var self = self || {},
|
|
that = new Ox.Element({}, self)
|
|
.defaults({
|
|
elements: [],
|
|
orientation: "horizontal"
|
|
})
|
|
.options(options || {})
|
|
.addClass("OxSplitPanel"),
|
|
length = self.options.elements.length,
|
|
dimensions = oxui.getDimensions(self.options.orientation),
|
|
edges = oxui.getEdges(self.options.orientation);
|
|
|
|
that.$elements = [];
|
|
|
|
$.each(self.options.elements, function(i, v) {
|
|
if (Ox.isUndefined(v.collapsible)) {
|
|
v.collapsible = false;
|
|
}
|
|
if (Ox.isUndefined(v.resizable)) {
|
|
v.resizable = false;
|
|
}
|
|
that.$elements[i] = v.element
|
|
.css(edges[2], 0)
|
|
.css(edges[3], 0);
|
|
});
|
|
|
|
setSizes();
|
|
|
|
$.each(self.options.elements, function(i, v) {
|
|
//that.append(element)
|
|
that.$elements[i].appendTo(that);
|
|
if (v.collapsible || v.resizable) {
|
|
Ox.print("v.size", v.size)
|
|
$resizebar = new Ox.Resizebar({
|
|
collapsible: v.collapsible,
|
|
edge: self.options.orientation == "horizontal" ?
|
|
(i == 0 ? "left" : "right") : (i == 0 ? "top" : "bottom"),
|
|
elements: i < 2 ?
|
|
[that.$elements[0], that.$elements[1]] :
|
|
[that.$elements[1], that.$elements[2]],
|
|
orientation: self.options.orientation == "horizontal" ? "vertical" : "horizontal",
|
|
parent: that,
|
|
resizable: v.resizable,
|
|
resize: v.resize,
|
|
size: v.size
|
|
})
|
|
.css(edges[i == 0 ? 0 : 1], v.size);
|
|
if (i == 0) {
|
|
$resizebar.appendTo(that);
|
|
} else {
|
|
$resizebar.prependTo(that);
|
|
}
|
|
}
|
|
});
|
|
|
|
function getPositionById(id) {
|
|
var position = -1;
|
|
$.each(self.options.elements, function(i, element) {
|
|
if (element.element.options("id") == id) {
|
|
position = 1;
|
|
return false;
|
|
}
|
|
});
|
|
return position;
|
|
}
|
|
|
|
function getSize(element) {
|
|
return element.size + element.resizable;
|
|
}
|
|
|
|
function setSizes() {
|
|
$.each(self.options.elements, function(i, v) {
|
|
!Ox.isUndefined(v.size) && that.$elements[i].css(dimensions[0], v.size + "px");
|
|
if (i == 0) {
|
|
that.$elements[i].css(edges[0], 0);
|
|
!Ox.isUndefined(v.size) && that.$elements[i].css(
|
|
edges[1], (getSize(self.options.elements[1]) + (length == 3 ? getSize(self.options.elements[2]) : 0)) + "px"
|
|
);
|
|
} else if (i == 1) {
|
|
!Ox.isUndefined(self.options.elements[0].size) && that.$elements[i].css(
|
|
edges[0], getSize(self.options.elements[0]) + "px"
|
|
);
|
|
(!Ox.isUndefined(self.options.elements[0].size) || !Ox.isUndefined(v.size)) && that.$elements[i].css(
|
|
edges[1], (length == 3 ? getSize(self.options.elements[2]) : 0) + "px"
|
|
);
|
|
} else {
|
|
that.$elements[i].css(edges[1], 0);
|
|
!Ox.isUndefined(v.size) && that.$elements[i].css(
|
|
edges[0], (getSize(self.options.elements[0]) + getSize(self.options.elements[1])) + "px"
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
that.resize = function(id, size) {
|
|
// one can pass pos instead of id
|
|
var pos = Ox.isNumber(id) ? id : getPositionById(id);
|
|
// Ox.print("pos", pos, self.options.elements, $.map(self.options.elements, function(v, i) { return v.element.options("id"); }))
|
|
self.options.elements[pos].size = size;
|
|
setSizes();
|
|
return that;
|
|
};
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
Ox.TabPanel = function(options, self) {
|
|
|
|
};
|
|
|
|
/*
|
|
============================================================================
|
|
Requests
|
|
============================================================================
|
|
*/
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.LoadingIcon
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
Ox.LoadingIcon = function(options, self) {
|
|
var self = self || {},
|
|
that = new Ox.Element("img", self)
|
|
.defaults({
|
|
size: "medium"
|
|
})
|
|
.options(options || {})
|
|
.attr({
|
|
src: oxui.path + "/png/ox.ui." + Ox.theme() + "/loading.png" // fixme: oxui.themePath needed?
|
|
})
|
|
.addClass(
|
|
"OxLoadingIcon Ox" + Ox.toTitleCase(self.options.size)
|
|
);
|
|
self.deg = 0;
|
|
self.interval = 0;
|
|
self.isRunning = false;
|
|
function clear() {
|
|
clearInterval(self.interval);
|
|
self.deg = 0;
|
|
self.interval = 0;
|
|
update();
|
|
}
|
|
function update() {
|
|
that.css({
|
|
MozTransform: "rotate(" + self.deg + "deg)",
|
|
WebkitTransform: "rotate(" + self.deg + "deg)"
|
|
});
|
|
}
|
|
that.start = function() {
|
|
self.isRunning = true;
|
|
clear();
|
|
that.animate({
|
|
opacity: 1
|
|
}, 250);
|
|
self.interval = setInterval(function() {
|
|
self.deg = (self.deg + 30) % 360;
|
|
update();
|
|
}, 83);
|
|
};
|
|
that.stop = function() {
|
|
that.animate({
|
|
opacity: 0
|
|
}, 250, function() {
|
|
!self.isRunning && clear();
|
|
self.isRunning = false;
|
|
});
|
|
}
|
|
return that;
|
|
}
|
|
|
|
/*
|
|
----------------------------------------------------------------------------
|
|
Ox.Progressbar
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
})(); |