/* ################################################################################ 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 = $("
"); //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 ---------------------------------------------------------------------------- */ Ox.Event = function() { var $eventHandler = $("
"), events = {}; function addEvent(id, type, event, callback) { events[id] = events[id] || {}; events[id][type] = events[id][type] || {}; events[id][type][event] = events[id][type][event] || []; events[id][type][event].push(callback); if (type == "normal" || Ox.Focus.focused() == id) { Ox.print("bind", id, event); $eventHandler.bind(event + "_" + id, callback); } } function removeEvent(id, type, event, callback) { var focused = type == "normal" || Ox.Focus.focused() == id, toString = (callback || "").toString(); Ox.print("removeEvent", id, type, event, callback); if (events[id] && events[id][type] && (!event || events[id][type][event])) { $.each(events[id][type], function(e, fns) { if (!event || event == e) { events[id][type][e] = $.map(events[id][type][e], function(fn, i) { if (!callback || toString == fn.toString()) { focused && $eventHandler.unbind(e + "_" + id, fn); return null; } else { return fn; } }); } }); Ox.print(id, type, events) if (!callback || (event && events[id][type][event].length == 0)) { delete events[id][type][event]; } if (!event || Ox.length(events[id].normal) == 0) { delete events[id][type]; } if (Ox.length(events[id]) == 0) { delete events[id]; } } } function isKeyboardEvent(event) { // fixme: currently unused return event.substr(0, 4) == "key_"; } return { _print: function() { Ox.print(events); }, add: function(id, event, callback) { // add keyboard event addEvent(id, "keyboard", event, callback); }, bind: function(id, event, callback) { // bind event addEvent(id, "normal", event, callback); }, bindKeyboard: function(id) { // bind all keyboard events //Ox.print("binding", "id", id, "events", events[id], Ox.length(events[id]), "keyboardevents", events[id]["keyboard"]) $.each(events[id], function(k, v) { Ox.print("|" + k + "|"); }) events[id] && events[id].keyboard && $.each(events[id].keyboard, function(event, callbacks) { $.each(callbacks, function(i, callback) { Ox.print("bind", id, event); $eventHandler.bind(event, callback); }); }); }, changeId: function(oldId, newId) { // fixme: would it be better to pass that.id instead of self.options.id? // then this renaming wouldn't be necessary Ox.print("changeId", oldId, newId, events[oldId]); $.each($.extend({}, events[oldId] || {}), function(type, events_) { var bind = type == "normal" ? "bind" : "add", unbind = type == "normal" ? "unbind" : "remove"; $.each(events_, function(event, callbacks) { $.each(callbacks, function(i, callback) { Ox.Event[unbind](oldId, event, callback); Ox.Event[bind](newId, event, callback); }); }); }); }, remove: function(id, event, callback) { // remove keyboard event // event and callback are optional removeEvent(id, "keyboard", event, callback); }, unbind: function(id, event, callback) { // unbind event // event and callback are optional removeEvent(id, "normal", event, callback); }, trigger: function(id, event, data) { // trigger event // data is optional // keyboard handler will call this with "" as id Ox.print("trigger", id, event, data || {}); $eventHandler.trigger(event + (id ? "_" + id : ""), data || {}); }, unbindKeyboard: function(id) { // unbind all keyboard events Ox.print("unbinding", id /*events[id].keyboard*/) events[id] && events[id].keyboard && $.each(events[id].keyboard, function(event, callbacks) { $.each(callbacks, function(i, callback) { Ox.print("unbind", event) $eventHandler.unbind(event, callback); }); }); } } }(); /* ---------------------------------------------------------------------------- Ox.Focus ---------------------------------------------------------------------------- */ Ox.Focus = function() { var stack = []; return { blur: function(id) { var index = stack.indexOf(id); if (index == stack.length - 1) { $elements[id].removeClass("OxFocus"); //$(".OxFocus").removeClass("OxFocus"); // fixme: the above is better, and should work stack.length == 1 ? stack.pop() : stack.splice(stack.length - 2, 0, stack.pop()); Ox.Event.unbindKeyboard($elements[id].options("id")); stack.length && Ox.Event.bindKeyboard($elements[stack[stack.length - 1]].options("id")); Ox.print("blur", id, stack); } }, focus: function(id) { var index = stack.indexOf(id); if (index == -1 || index < stack.length - 1) { stack.length && Ox.Event.unbindKeyboard($elements[stack[stack.length - 1]].options("id")); index > -1 && stack.splice(index, 1); stack.push(id); $elements[id].addClass("OxFocus"); Ox.Event.bindKeyboard($elements[id].options("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 = $("