");
//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", ""),
symbols: { // fixme: make lowercase
alt: "\u2325",
apple: "\uF8FF",
arrow_down: "\u2193",
arrow_left: "\u2190",
arrow_right: "\u2192",
arrow_up: "\u2191",
backspace: "\u232B",
backup: "\u2707",
ballot: "\u2717",
black_star: "\u2605",
burn: "\u2622",
caps_lock: "\u21EA",
check: "\u2713",
clear: "\u2327",
click: "\uF803",
close: "\u2715",
command: "\u2318",
control: "\u2303",
cut: "\u2702",
"delete": "\u2326",
diamond: "\u25C6",
edit: "\uF802",
eject: "\u23CF",
escape: "\u238B",
end: "\u2198",
enter: "\u2324",
fly: "\u2708",
gear: "\u2699",
home: "\u2196",
info: "\u24D8",
navigate: "\u2388",
option: "\u2387",
page_up: "\u21DE",
page_down: "\u21DF",
redo: "\u21BA",
"return": "\u21A9",
select: "\u21D5",
shift: "\u21E7",
sound: "\u266B",
space: "\u2423",
tab: "\u21E5",
trash: "\u267A",
triangle_down: "\u25BC",
triangle_left: "\u25C0",
triangle_right: "\u25BA",
triangle_up: "\u25B2",
undo: "\u21BB",
voltage: "\u26A1",
warning: "\u26A0",
white_star: "\u2606"
}
},
$window, $document, $body;
$(function() {
$window = $(window),
$document = $(document),
$body = $("body");
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() {
};
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 = $("
");
function isKeyboardEvent(event) {
return event.substr(0, 4) == "key_";
}
return {
bind: function(id, event, callback) {
if (isKeyboardEvent(event)) {
keyboardEvents[id] = keyboardEvents[id] || {};
keyboardEvents[id][event] = callback;
}
if (!isKeyboardEvent(event) || Ox.Focus.focused() == id) {
$eventHandler.bind(event, callback);
}
},
bindKeyboard: function(id) {
$.each(keyboardEvents[id] || [], function(event, callback) {
Ox.Event.bind(id, 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;
}
});
}
$eventHandler.unbind(event, callback);
},
unbindKeyboard: function(id) {
$.each(keyboardEvents[id] || [], function(event, callback) {
$eventHandler.unbind(event, callback);
});
}
}
}();
Ox.Event_ = function() {
var events = {};
return {
// make these bind, trigger, unbind
publish: function(event, data) {
Ox.print("publish", event, data);
if (events[event]) {
$.each(events[event], function(i, v) {
setTimeout(function() {
v(data);
}, 0);
});
}
},
subscribe: function(event, callback) {
Ox.print("subscribe", event, callback);
if (events[event]) {
events[event].push(callback);
} else {
events[event] = [callback];
}
},
unsubscribe: function(event, callback) {
Ox.print("unsubscribe", 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 {
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);
Ox.Event.bindKeyboard(id);
Ox.print("focus", stack);
},
focused: function() {
return stack[stack.length - 1];
},
blur: function(id) {
if (stack.indexOf(id) > -1) {
stack.splice(stack.length - 2, 0, stack.pop());
}
Ox.Event.unbindKeyboard(id);
Ox.Event.bindKeyboard(stack[stack.length - 1]);
Ox.print("blur", stack);
}
};
}();
/*
----------------------------------------------------------------------------
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
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) {
options = $.extend({
age: -1,
callback: function() {},
id: Ox.uid(),
timeout: self.options.timeout,
type: self.options.type,
url: self.options.url
}, options);
var req = JSON.stringify({
url: options.url,
data: options.data
});
function callback(data) {
delete requests[options.id];
options.callback(data);
}
function debug(request) {
var $iframe = $("