"),
+ 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) {
- 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);
- }
+ // bind event
+ addEvent(id, "normal", event, callback);
},
bindKeyboard: function(id) {
- $.each(keyboardEvents[id] || [], function(event, callback) {
- Ox.Event.bind(id, event, callback);
- //$eventHandler.bind(event, callback);
+ // 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);
+ });
});
},
- trigger: function(event, data) {
- Ox.print("trigger", event, data || {});
- $eventHandler.trigger(event, data || {});
+ 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) {
- 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);
+ // 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) {
- $.each(keyboardEvents[id] || [], function(event, callback) {
- Ox.print("unbind", id, event)
- $eventHandler.unbind(event, callback);
+ // 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.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
@@ -296,27 +310,27 @@ requires
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]);
+ 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 (stack.length) {
- Ox.Event.unbindKeyboard(stack[stack.length - 1])
+ 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);
}
- 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];
@@ -511,7 +525,7 @@ requires
buffer += key == "SPACE" ? " " : key;
bufferTime = time;
}
- Ox.Event.trigger("key_" + key);
+ Ox.Event.trigger("", "key_" + key);
//return false;
/*
$.each(stack, function(i, v) {
@@ -750,9 +764,11 @@ requires
// 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)
+ var that = new Ox.Element("div", self)
+ .options(options || {})
.addClass("OxContainer");
- that.$content = new Ox.Element(options, self)
+ that.$content = new Ox.Element("div", self)
+ .options(options || {})
.addClass("OxContent")
.appendTo(that);
return that;
@@ -768,8 +784,6 @@ requires
Ox.Element = function() {
- var elements = {}; // fixme: unused, we need this outside Element (for Focus)
-
return function(options, self) {
// construct
@@ -863,21 +877,37 @@ requires
};
// public
- that.bindEvent = function() {
- // fixme: shouldn't this work the other way around,
- // and bind a function to an event triggered by this widget?
+
+ that.addEvent = function() {
/*
+ adds a keyboard event, to be bound when focused
+ addEvent(event, fn) or addEvent({event0: fn0, event1: fn1, ...})
+ */
+ if (arguments.length == 1) {
+ $.each(arguments[0], function(event, fn) {
+ Ox.Event.add(self.options.id, event, fn);
+ });
+ } else {
+ Ox.Event.add(self.options.id, arguments[0], arguments[1]);
+ }
+ return that;
+ };
+
+ that.bindEvent = function() {
+ /*
+ binds a function to an event triggered by this object
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);
+ Ox.Event.bind(self.options.id, event, fn);
});
} else {
- Ox.Event.bind(that.id, arguments[0], arguments[1]);
+ Ox.Event.bind(self.options.id, arguments[0], arguments[1]);
}
return that;
- };
+ }
+
that.defaults = function(defaults) {
/*
that.defaults({foo: x}) sets self.defaults
@@ -886,17 +916,21 @@ requires
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
@@ -908,7 +942,7 @@ requires
returns that
*/
var length = arguments.length,
- // args, options, ret;
+ id = self.options && self.options.id,
args, ret;
if (length == 0) {
// options()
@@ -927,6 +961,7 @@ requires
// otherwise, extend options
self.options = $.extend(self.options || self.defaults, args);
$.each(args, function(key, value) {
+ key == "id" && id && Ox.Event.changeId(id, value);
self.onChange(key, value);
/*
fixme: why does this not work?
@@ -944,34 +979,54 @@ requires
}
return ret;
};
+
that.remove = function() {
that.$element.remove();
delete $elements[that.ox];
return that;
};
- that.triggerEvent = function() {
+
+ that.removeEvent = function() {
/*
- triggerEvent(event, fn) or triggerEvent({event0: fn0, event1: fn1, ...})
+ removes a keyboard event
+ removeEvent(event, fn) or removeEvent({event0: fn0, event1: fn1, ...})
*/
- if (Ox.isObject(arguments[0])) {
+ if (arguments.length == 1) {
$.each(arguments[0], function(event, fn) {
- Ox.Event.trigger(event + "_" + self.options.id, fn);
+ Ox.Event.remove(self.options.id, event, fn);
});
} else {
- Ox.Event.trigger(arguments[0] + "_" + self.options.id, arguments[1] || {});
+ Ox.Event.remove(self.options.id, arguments[0], arguments[1]);
}
return that;
};
+
+ that.triggerEvent = function() {
+ /*
+ triggers an event
+ triggerEvent(event) or triggerEvent(event, data) or triggerEvent({event0: data, event1: data, ...})
+ */
+ if (Ox.isObject(arguments[0])) {
+ $.each(arguments[0], function(event, data) {
+ Ox.Event.trigger(self.options.id, event, data);
+ });
+ } else {
+ Ox.Event.trigger(self.options.id, arguments[0], arguments[1] || {});
+ }
+ return that;
+ };
+
that.unbindEvent = function() {
/*
+ unbinds an event
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);
- })
+ Ox.Event.unbind(self.options.id, event, fn);
+ });
} else {
- Ox.Event.unbind(that.id, arguments[0], arguments[1]);
+ Ox.Event.unbind(self.options.id, arguments[0], arguments[1]);
}
return that;
};
@@ -1326,8 +1381,8 @@ requires
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]]());
+ Ox.Event.trigger(self.ids[0], "resize", self.options.size);
+ Ox.Event.trigger(self.ids[1], "resize", self.options.elements[1][self.dimensions[1]]());
}
function dragStart(e) {
@@ -1460,7 +1515,7 @@ requires
that.$buttons[i] = new Ox.Button({
disabled: button.disabled || false,
size: "medium",
- value: button.value // fixme: use title
+ title: button.title
})
.addClass("OxLeft")
.click(button.click) // fixme: rather use event?
@@ -1476,7 +1531,7 @@ requires
disabled: button.disabled || false,
id: button.id,
size: "medium",
- value: button.value
+ title: button.title
})
.addClass("OxRight")
.click(button.click) // fixme: rather use event?
@@ -1730,10 +1785,11 @@ requires
var id = item.element.options("id");
that.append(self.$items[i] = new Ox.FormItem(item))
.append(self.$messages[i] = new Ox.Element().addClass("OxFormMessage"));
- Ox.Event.bind("validate_" + id, function(event, data) {
+ // fixme: use widget.bindEvent()
+ Ox.Event.bind(id, "validate", function(event, data) {
validate(i, data.valid);
});
- Ox.Event.bind("blur_" + id, function(event, data) {
+ Ox.Event.bind(id, "blur", function(event, data) {
validate(i, data.valid);
if (data.valid) {
self.$messages[i].html("").hide();
@@ -1741,7 +1797,7 @@ requires
self.$messages[i].html(data.message).show();
}
});
- Ox.Event.bind("submit_" + id, function(event, data) {
+ Ox.Event.bind(id, "submit", function(event, data) {
self.formIsValid && that.submit();
});
});
@@ -1816,92 +1872,116 @@ requires
/*
----------------------------------------------------------------------------
- Ox.Button
+ Form Elements
----------------------------------------------------------------------------
*/
Ox.Button = function(options, self) {
/*
events:
- click non-selectable button was clicked
- deselect selectable button was deselected
- select selectable button was selected
+ 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,
+ group: false,
id: "",
+ overlap: "none",
selectable: false,
selected: false,
size: "medium",
- style: "default", // can be default, symbol or tab
+ // fixme: "default" or ""?
+ style: "default", // can be default, checkbox, symbol, or tab
+ title: "",
+ tooltip: "",
type: "text",
- value: "",
- values: [] // fixme: shouldn't this go into self.values?
+ width: "auto"
})
- .options($.extend(options, {
- value: $.isArray(options.value) ?
- options.value[0] : options.value,
- values: $.makeArray(options.value)
- }))
+ .options(options || {})
.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": ""))
+ (self.options.selected ? " OxSelected": "") +
+ (self.options.style != "default" ? " Ox" + Ox.toTitleCase(self.options.style) : "") +
+ (self.options.overlap != "none" ? " OxOverlap" + Ox.toTitleCase(self.options.overlap) : ""))
+ .css(self.options.width == "auto" ? {} : {
+ width: (self.options.width - 14) + "px"
+ })
.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();
- }
+
+ $.extend(self, Ox.isArray(self.options.title) ? {
+ selectedTitle: Ox.setPropertyOnce(self.options.title, "selected"),
+ titles: self.options.title
+ } : {
+ selectedTitle: 0,
+ titles: [{
+ id: "",
+ title: self.options.title
+ }]
+ });
+
+ setTitle(self.titles[self.selectedTitle].title);
+
+ if (self.options.tooltip) {
+ self.tooltips = Ox.isArray(self.options.tooltip) ? self.options.tooltip : [self.options.tooltip];
+ self.$tooltip = new Ox.Tooltip({
+ title: self.tooltips[self.selectedTitle]
+ });
+ that.mouseenter(mouseenter)
+ .mouseleave(mouseleave);
}
+
function click() {
+ var data = self.titles[self.selectedTitle];
if (!self.options.selectable) {
- that.triggerEvent("click");
- } else if (!self.options.group || !self.options.selected) {
+ that.triggerEvent("click", data);
+ } else {
if (self.options.group) {
- that.triggerEvent("select");
+ that.triggerEvent("select", data);
} 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]
- });
+ if (self.titles.length == 2) {
+ that.toggleTitle();
}
- //self.options.click();
}
+
+ function mousedown(event) {
+ if (self.options.type == "image" && $.browser.safari) {
+ // keep image from being draggable
+ event.preventDefault();
+ }
+ }
+
+ function mouseenter(event) {
+ self.$tooltip.show(event.clientX, event.clientY);
+ }
+
+ function mouseleave(event) {
+ self.$tooltip.hide();
+ }
+
+ function setTitle(title) {
+ self.title = title;
+ if (self.options.type == "image") {
+ that.attr({
+ src: oxui.path + "png/ox.ui." + Ox.theme() +
+ "/symbol" + Ox.toTitleCase(title) + ".png"
+ });
+ } else {
+ that.val(title);
+ }
+ }
+
self.onChange = function(key, value) {
- //Ox.print("setOption", option, value)
if (key == "disabled") {
that.attr({
disabled: value ? "disabled" : ""
@@ -1912,493 +1992,2882 @@ requires
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);
- }
+ } else if (key == "title") {
+ setTitle(value);
+ } else if (key == "width") {
+ that.$element.css({
+ width: (value - 14) + "px"
+ });
}
}
+
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
- ----------------------------------------------------------------------------
- */
+ that.toggleTitle = function() {
+ self.selectedTitle = 1 - self.selectedTitle;
+ setTitle(self.titles[self.selectedTitle].title);
+ self.$tooltip.options({
+ title: self.tooltips[self.selectedTitle]
+ });
+ }
+
+ return that;
+
+ };
Ox.ButtonGroup = function(options, self) {
/*
+ Ox.ButtonGroup
+ options:
+ buttons array of buttons
+ max integer, maximum number of selected buttons, 0 for all
+ min integer, minimum number of selected buttons, 0 for none
+ selectable if true, buttons are selectable
+ type string, "image" or "text"
events:
- change {id, value} selection within a group changed
+ change {id, value} selection within a group changed
*/
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
buttons: [],
- group: false,
+ max: 1,
+ min: 1,
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
- });
+ if (self.options.selectable) {
+ self.optionGroup = new Ox.OptionGroup(
+ self.options.buttons,
+ self.options.min,
+ self.options.max,
+ "selected"
+ );
+ self.options.buttons = self.optionGroup.init();
}
- function selectButton(position) {
- that.$buttons[self.options.selected].toggleSelected();
- self.options.selected = position;
- that.$buttons[self.options.selected].toggleSelected();
- };
+ self.$buttons = [];
+ $.each(self.options.buttons, function(position, button) {
+ var id = self.options.id + Ox.toTitleCase(button.id)
+ self.$buttons[position] = Ox.Button({
+ disabled: button.disabled,
+ group: true,
+ id: id,
+ selectable: self.options.selectable,
+ selected: button.selected,
+ size: self.options.size,
+ style: self.options.style,
+ title: button.title,
+ type: self.options.type
+ })
+ .bindEvent("select", function() {
+ selectButton(position);
+ })
+ .appendTo(that);
+ });
+
+ function selectButton(pos) {
+ var toggled = self.optionGroup.toggle(pos);
+ if (toggled.length) {
+ $.each(toggled, function(i, pos) {
+ self.$buttons[pos].toggleSelected();
+ });
+ that.triggerEvent("change", {
+ selected: $.map(self.optionGroup.selected(), function(v, i) {
+ return self.options.buttons[v].id;
+ })
+ });
+ }
+ }
return that;
};
- /*
- ----------------------------------------------------------------------------
- Ox.Input
- ----------------------------------------------------------------------------
- */
+ Ox.Checkbox = function(options, self) {
- Ox.Input = function(options, self) {
-
- /* options:
- * autocomplete function, or array of values, or dict with array of values per label or placeholder
- * autocorrect function for live correction
- * clear boolean, clear button, or not
- * highlight boolean, highlight value in autocomplete menu, or not
- * id
- * label string or array [{id, title}] (select) -- label and placeholder are mutually exclusive
- * labelWidth integer (px)
- * placeholder string or array [{id, title}] (select) -- label and placeholder are mutually exclusive
- * selected integer, selected label or placeholder
- * size "large", "medium" or "small"
- * type "text", "password", "textarea", etc.
- * validate function vor live validation, returns { message: "", valid: false }
- * value string
- */
+ /***
+ Ox.Checkbox
+ Checkbox Form Element
+ Options:
+ disabled boolean, if true, checkbox is disabled
+ id element id
+ group boolean, if true, checkbox is part of a group
+ checked boolean, if true, checkbox is checked
+ title string, text on label
+ width integer, width in px
+ Methods:
+ toggleChecked function()
+ toggles checked property
+ returns that
+ Events:
+ change triggered when checked property changes
+ passes {checked, id, title}
+ ***/
var self = self || {},
that = new Ox.Element("div", self)
.defaults({
- autocomplete: null,
- autocorrect: null,
- clear: false,
- highlight: false,
+ disabled: false,
id: "",
- label: "",
- labelWidth: 64,
- placeholder: "",
- selected: 0,
- size: "medium",
- type: "text",
- validate: null,
- value: ""
+ group: false,
+ checked: false,
+ title: "",
+ width: "auto"
})
.options(options || {})
- .addClass("OxInput Ox" + Ox.toTitleCase(self.options.size)),
- autocomplete; // fixme: should be self.autocomplete
+ .addClass("OxCheckbox")
+ .attr(self.options.disabled ? {
+ disabled: "disabled"
+ } : {});
- 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.length == 1 ? self.options.label[0] : 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
+ if (self.options.title) {
+ self.options.width != "auto" && that.css({
+ width: self.options.width + "px"
+ });
+ self.$title = new Ox.Label({
+ disabled: self.options.disabled,
+ id: self.options.id + "Label",
+ overlap: "left",
+ title: self.options.title,
+ width: self.options.width - 16
})
- .click(select)
+ .css({
+ float: "right"
+ })
+ .click(clickTitle)
.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?
+ self.$button = new Ox.Button({
+ disabled: self.options.disabled,
+ id: self.options.id + "Button",
+ title: [
+ {id: "none", title: "none", selected: !self.options.checked},
+ {id: "check", title: "check", selected: self.options.checked}
+ ],
+ type: "image"
})
- .addClass(
- "OxInput Ox" + Ox.toTitleCase(self.options.size) +
- " OxPlaceholder"
- )
- .focus(focus)
- .blur(blur)
- .change(change)
+ .addClass("OxCheckbox")
+ .click(clickButton)
.appendTo(that);
- self.options.placeholder && that.$input.val(self.option.title);
+ function clickButton() {
+ self.options.checked = !self.options.checked;
+ // click will have toggled the button,
+ // if it is part of a group, we have to revert that
+ self.options.group && that.toggleChecked();
+ that.triggerEvent("change", {
+ checked: self.options.checked,
+ id: self.options.id,
+ title: self.options.title
+ });
+ }
+
+ function clickTitle() {
+ !self.options.disabled && self.$button.trigger("click");
+ }
+
+ self.onChange = function(key, value) {
+ if (key == "checked") {
+ that.toggleChecked();
+ }
+ };
+
+ that.toggleChecked = function() {
+ self.$button.toggleTitle();
+ return that;
+ }
+
+ return that;
+
+ };
+
+ Ox.CheckboxGroup = function(options, self) {
+
+ var self = self || {},
+ that = new Ox.Element("div", self)
+ .defaults({
+ checkboxes: [],
+ max: 1,
+ min: 1,
+ width: 256
+ })
+ .options(options || {})
+ .addClass("OxCheckboxGroup");
+
+ self.optionGroup = new Ox.OptionGroup(
+ self.options.checkboxes,
+ self.options.min,
+ self.options.max);
+ self.options.checkboxes = self.optionGroup.init();
+
+ $.extend(self, {
+ $checkboxes: [],
+ checkboxWidth: $.map(Ox.divideInt(
+ self.options.width + (self.options.checkboxes.length - 1) * 6,
+ self.options.checkboxes.length
+ ), function(v, i) {
+ return v + (i < self.options.checkboxes.length - 1 ? 10 : 0);
+ })
+ })
+ $.each(self.options.checkboxes, function(position, checkbox) {
+ var id = self.options.id + Ox.toTitleCase(checkbox.id)
+ self.$checkboxes[position] = new Ox.Checkbox($.extend(checkbox, {
+ group: true,
+ id: id,
+ width: self.checkboxWidth[position]
+ }))
+ .bindEvent("change", function() {
+ change(position);
+ })
+ .appendTo(that);
+ });
+
+ function change(pos) {
+ var toggled = self.optionGroup.toggle(pos);
+ //Ox.print("change", pos, "toggled", toggled)
+ if (toggled.length) {
+ $.each(toggled, function(i, pos) {
+ self.$checkboxes[pos].toggleChecked();
+ });
+ that.triggerEvent("change", {
+ checked: $.map(self.optionGroup.checked(), function(v, i) {
+ return self.options.checkboxes[v].id;
+ })
+ });
+ }
+ }
+
+ return that;
+
+ };
+
+ Ox.Input = function(options, self) {
+
+ /*
+ options:
+ arrows boolearn, if true, and type is "float" or "integer", display arrows
+ arrowStep number, step when clicking arrows
+ autocomplete array of possible values, or
+ function(key, value, callback), returns one or more values
+ autocompleteReplace boolean, if true, value is replaced
+ autocompleteReplaceCorrect boolean, if true, only valid values can be entered
+ autocompleteSelect boolean, if true, menu is displayed
+ autocompleteSelectHighlight boolean, if true, value in menu is highlighted
+ autocompleteSelectSubmit boolean, if true, submit input on menu selection
+ autovalidate string ("email", "float", "integer", "phone", "url"), or
+ regexp(value), or
+ function(key, value, blur, callback), returns value
+ clear boolean, if true, has clear button
+ disabled boolean, if true, is disabled
+ height integer, px (for type="textarea" and type="range" with orientation="horizontal")
+ id string, element id
+ key string, to be passed to autocomplete and autovalidate functions
+ max number, max value if type is "integer" or "float"
+ min number, min value if type is "integer" or "float"
+ name string, will be displayed by autovalidate function ("invalid " + name)
+ overlap string, "", "left" or "right", will cause padding and negative margin
+ picker
+ //rangeOptions
+ arrows boolean, if true, display arrows
+ //arrowStep number, step when clicking arrows
+ //arrowSymbols array of two strings
+ max number, maximum value
+ min number, minimum value
+ orientation "horizontal" or "vertical"
+ step number, step
+ thumbValue boolean, if true, value is displayed on thumb, or
+ array of strings per value, or
+ function(value), returns string
+ thumbSize integer, px
+ trackGradient string, css gradient for track
+ trackImage string, image url, or
+ array of image urls
+ //trackStep number, 0 for "scroll here", positive for step
+ trackValues boolean
+ serialize
+ textAlign "left", "center" or "right"
+ type "float", "integer", "password", "text"
+ value string
+ width integer, px
+ methods:
+ events:
+ change
+ submit
+ */
+
+ var self = self || {},
+ that = new Ox.Element("div", self)
+ .defaults({
+ arrows: false,
+ arrowStep: 1,
+ autocomplete: null,
+ autocompleteReplace: false,
+ autocompleteReplaceCorrect: false,
+ autocompleteSelect: false,
+ autocompleteSelectHighlight: false,
+ autocompleteSelectSubmit: false,
+ autovalidate: null,
+ clear: false,
+ key: "",
+ min: 0,
+ max: 100,
+ label: "",
+ labelWidth: 64,
+ overlap: "none",
+ placeholder: "",
+ serialize: null,
+ textAlign: "left",
+ type: "text",
+ value: "",
+ width: 128
+ })
+ .options(options)
+ .addClass("OxInput OxMedium")
+ .addEvent($.extend(self.options.type == "textarea" ? {} : {
+ key_enter: submit
+ }, {
+ key_escape: cancel
+ }));
+
+ if (
+ Ox.isArray(self.options.autocomplete) &&
+ self.options.autocompleteReplace &&
+ self.options.autocompleteReplaceCorrect &&
+ self.options.value === ""
+ ) {
+ self.options.value = self.options.autocomplete[0]
+ }
+
+ // fixme: set to min, not 0
+ if (self.options.type == "float") {
+ $.extend(self.options, {
+ autovalidate: "float",
+ textAlign: "right",
+ value: self.options.value || "0.0"
+ });
+ } else if (self.options.type == "integer") {
+ $.extend(self.options, {
+ autovalidate: "integer",
+ textAlign: "right",
+ value: self.options.value || "0"
+ });
+ }
+
+ if (self.options.label) {
+ self.$label = new Ox.Label({
+ overlap: "right",
+ textAlign: "right",
+ title: self.options.label,
+ width: self.options.labelWidth
+ })
+ .css({
+ float: "left", // fixme: use css rule
+ })
+ .click(function() {
+ that.focus();
+ })
+ .appendTo(that);
+ }
+
+ if (self.options.arrows) {
+ self.arrows = [];
+ self.arrows[0] = [
+ new Ox.Button({
+ overlap: "right",
+ title: "previous",
+ type: "image"
+ })
+ .css({
+ float: "left"
+ })
+ .click(function() {
+ clickArrow(0);
+ })
+ .appendTo(that),
+ new Ox.Button({
+ overlap: "left",
+ title: "next",
+ type: "image"
+ })
+ .css({
+ float: "right"
+ })
+ .click(function() {
+ clickArrow(1);
+ })
+ .appendTo(that)
+ ]
+ }
+
+ $.extend(self, {
+ bindKeyboard: self.options.autocomplete || self.options.autovalidate,
+ hasPasswordPlaceholder: self.options.type == "password" && self.options.placeholder,
+ inputWidth: getInputWidth()
+ });
if (self.options.clear) {
- that.$clear = new Ox.Button({
- style: "symbol",
- type: "image",
- value: "clear"
- //value: oxui.symbols.clear
+ self.$button = new Ox.Button({
+ overlap: "left",
+ title: "clear",
+ type: "image"
+ })
+ .css({
+ float: "right" // fixme: use css rule
})
.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);
+ self.$input = $("
")
+ .addClass("OxInput OxMedium")
+ .attr({
+ disabled: self.options.disabled ? "disabled" : "",
+ type: self.options.type == "password" ? "password" : "text"
+ })
+ .css({
+ width: self.inputWidth + "px",
+ textAlign: self.options.textAlign
+ })
+ .val(self.options.value)
+ .blur(blur)
+ .change(change)
+ .focus(focus)
+ .appendTo(that.$element);
+
+ if (self.hasPasswordPlaceholder) {
+ self.$input.hide();
+ self.$placeholder = $("
")
+ .addClass("OxInput OxMedium OxPlaceholder")
+ .attr({
+ type: "text"
+ })
+ .css({
+ //float: "left",
+ width: self.inputWidth + "px"
+ })
+ .val(self.options.placeholder)
+ .focus(focus)
+ .appendTo(that.$element);
}
- if (self.options.type != "textarea") {
- that.bindEvent({
- key_enter: submit,
- });
+ if (self.options.autocomplete && self.options.autocompleteSelect) {
+ self.$autocompleteMenu = new Ox.Menu({
+ element: self.$input,
+ id: self.options.id + "Menu", // fixme: we do this in other places ... are we doing it the same way? var name?,
+ offset: {
+ left: 4,
+ top: 0
+ },
+ size: self.options.size
+ })
+ .bindEvent("click", clickMenu);
+ if (self.options.autocompleteReplace) {
+ self.$autocompleteMenu.bindEvent({
+ deselect: deselectMenu,
+ select: selectMenu,
+ });
+ }
+ }
+
+ self.options.placeholder && setPlaceholder();
+
+ function autocomplete(oldValue, oldCursor) {
+
+ if (self.options.value || self.options.autocompleteReplaceCorrect) {
+ Ox.isFunction(self.options.autocomplete) ?
+ (self.options.key ? self.options.autocomplete(
+ self.options.key,
+ self.options.value,
+ autocompleteCallback
+ ) : self.options.autocomplete(
+ self.options.value,
+ autocompleteCallback
+ )) : autocompleteCallback(autocompleteFunction(self.options.value));
+ }
+ if (!self.options.value) {
+ self.options.autocompleteSelect && self.$autocompleteMenu.hideMenu();
+ }
+
+ function autocompleteFunction() {
+ var values = Ox.find(self.options.autocomplete, self.options.value);
+ return self.options.autocompleteReplace ? values[0] :
+ $.merge(values[0], values[1]);
+ }
+
+ function autocompleteCallback(values) {
+
+ Ox.print("autocompleteCallback", values[0], self.options.value, self.options.value.length, oldValue, oldCursor)
+
+ var length = self.options.value.length,
+ deleted = length <= oldValue.length - (oldCursor[1] - oldCursor[0]),
+ newValue = values[0] ?
+ ((self.options.autocompleteReplaceCorrect || !deleted) ?
+ values[0] : self.options.value) :
+ (self.options.autocompleteReplaceCorrect ? oldValue : self.options.value),
+ newLength = newValue.length,
+ pos = cursor(),
+ selected = -1,
+ selectEnd = length == 0 || (values[0] && values[0].length),
+ value;
+
+ Ox.print("selectEnd", selectEnd)
+
+ if (self.options.autocompleteReplace) {
+ self.options.value = newValue;
+ self.$input.val(self.options.value);
+ if (selectEnd) {
+ cursor(length, newLength);
+ } else if (self.options.autocompleteReplaceCorrect) {
+ cursor(oldCursor);
+ } else {
+ cursor(pos);
+ }
+ selected = 0;
+ }
+
+ if (self.options.autocompleteSelect) {
+ value = self.options.value.toLowerCase();
+ if (values.length) {
+ self.oldCursor = cursor();
+ self.oldValue = self.options.value;
+ self.$autocompleteMenu.options({
+ items: $.map(values, function(v, i) {
+ if (value == v.toLowerCase()) {
+ selected = i;
+ }
+ return {
+ id: v.toLowerCase().replace(/ /g, "_"), // fixme: need function to do lowercase, underscores etc?
+ title: self.options.autocompleteSelectHighlight ? v.replace(
+ new RegExp("(" + value + ")", "ig"),
+ "
$1"
+ ) : v
+ };
+ }),
+ selected: selected
+ }).showMenu();
+ } else {
+ self.$autocompleteMenu.hideMenu();
+ }
+ }
+
+ that.triggerEvent("autocomplete", {
+ value: newValue
+ });
+
+ }
+
+ }
+
+ function autovalidate() {
+
+ var blur, oldCursor, oldValue;
+
+ if (arguments.length == 1) {
+ blur = arguments[0];
+ } else {
+ blur = false;
+ oldValue = arguments[0];
+ oldCursor = arguments[1];
+ }
+
+ Ox.isFunction(self.options.autovalidate) ?
+ (self.options.key ? self.options.autovalidate(
+ self.options.key,
+ self.options.value,
+ blur,
+ autovalidateCallback
+ ) : self.options.autovalidate(
+ self.options.value,
+ blur,
+ autovalidateCallback
+ )) : Ox.isRegExp(self.options.autovalidate) ?
+ autovalidateCallback(autovalidateFunction(self.options.value)) :
+ autovalidateTypeFunction(self.options.type, self.options.value);
+
+ function autovalidateFunction(value) {
+ var regexp = new RegExp(self.options.autovalidate);
+ return $.map(value.toLowerCase().split(""), function(v, i) {
+ if (regexp(v)) {
+ return v;
+ } else {
+ return null;
+ }
+ }).join("");
+ }
+
+ function autovalidateTypeFunction(type, value) {
+ var cursor,
+ regexp = type == "float" ? /[\d\.]/ : /\d/;
+ if (type == "float") {
+ if (value.indexOf(".") != value.lastIndexOf(".")) {
+ value = oldValue;
+ } else {
+ if (self.autovalidateFloatFlag) {
+ if (Ox.endsWith(value, ".")) {
+ value = value.substr(0, value.length - 1);
+ }
+ self.autovalidateFloatFlag = false;
+ }
+ while (Ox.startsWith(value, ".")) {
+ if (Ox.startsWith(value, "..")) {
+ value = value.substr(1);
+ } else {
+ value = "0" + value;
+ }
+ }
+ if (Ox.endsWith(value, ".")) {
+ value += "0";
+ cursor = [value.length - 1, value.length];
+ self.autovalidateFloatFlag = true;
+ }
+ }
+ }
+ value = $.map(value.split(""), function(v, i) {
+ if (regexp(v)) {
+ return v;
+ } else {
+ return null;
+ }
+ }).join("");
+ if (type == "integer") {
+ while (value.length > 1 && Ox.startsWith(value, "0")) {
+ value = value.substr(1);
+ }
+ }
+ if (value === "") {
+ value = type == "float" ? "0.0" : "0";
+ cursor = [0, value.length];
+ } else if (value > self.options.max) {
+ value = oldValue;
+ }
+ autovalidateCallback(value, cursor);
+ }
+
+ function autovalidateCallback(newValue, newCursor) {
+ Ox.print("autovalidateCallback", newValue, oldCursor)
+ self.options.value = newValue;
+ self.$input.val(self.options.value);
+ !blur && cursor(
+ newCursor || (oldCursor[1] + newValue.length - oldValue.length)
+ );
+ that.triggerEvent("autovalidate", {
+ value: self.options.value
+ });
+ }
+
}
/*
- if (self.options.validate) {
- self.valid = self.options.validate(self.options.value);
+
+ function autovalidate(blur) {
+ Ox.print("autovalidate", self.options.value, blur || false)
+ self.autocorrectBlur = blur || false;
+ self.autocorrectCursor = cursor();
+ Ox.isFunction(self.options.autocorrect) ?
+ (self.options.key ? self.options.autocorrect(
+ self.options.key,
+ self.options.value,
+ self.autocorrectBlur,
+ autocorrectCallback
+ ) : self.options.autocorrect(
+ self.options.value,
+ self.autocorrectBlur,
+ autocorrectCallback
+ )) : autocorrectCallback(autocorrect(self.options.value));
}
+
+ function autovalidateFunction(value) {
+ var length = value.length;
+ return $.map(value.toLowerCase().split(""), function(v, i) {
+ if (new RegExp(self.options.autocorrect)(v)) {
+ return v;
+ } else {
+ return null;
+ }
+ }).join("");
+ }
+
*/
- that.bindEvent({
- key_escape: cancel
- });
-
- function autocomplete(value) {
- 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);
- }
- });
- }
- autocompleteCallback(items);
- }
-
- function autocompleteCall() {
- 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, autocompleteCallback) :
- self.options.autocomplete(value, autocompleteCallback)
- ) : autocomplete(value);
- } else {
- autocompleteCallback();
- }
- }
- }
-
- function autocompleteCallback(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"),
- "
$1"
- ) : title
- };
- });
- self.selectMenu.hideMenu();
- self.autocompleteMenu.options({
- items: items,
- selected: selected
- }).showMenu();
- } else {
- self.autocompleteMenu.hideMenu();
- }
- }
-
- function autocorrect(blur) {
- var blur = blur || false,
- length = self.value.length;
- pos = cursor(),
- self.value = self.options.autocorrect(self.value, blur);
- that.$input.val(self.value);
- if (!blur) {
- cursor(pos + self.value.length - length);
- }
- }
-
function blur() {
+ Ox.print("blur")
that.loseFocus();
- that.removeClass("OxFocus");
- self.options.autocorrect && autocorrect(that.$input.val(), true);
- self.options.validate && that.triggerEvent("blur", { // fixme: is this a good event name for validation on blur?
- message: self.message,
- valid: self.valid
- });
- if (self.options.placeholder && that.$input.val() === "") {
- that.$input.addClass("OxPlaceholder").val(self.option.title);
- }
- if (self.options.autocomplete || self.options.autocorrect || self.options.validate) { // fixme: duplicated, make a var
+ //that.removeClass("OxFocus");
+ self.options.value = self.$input.val();
+ self.options.autovalidate && autovalidate(true);
+ self.options.placeholder && setPlaceholder();
+ if (self.bindKeyboard) {
$document.unbind("keydown", keypress);
$document.unbind("keypress", keypress);
}
}
function cancel() {
- that.$input.blur();
+ self.$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();
- autocompleteCall();
- } else {
- if (that.$input.is(".OxPlaceholder")) {
- that.$input.val(self.option.title);
- //that.$input.focus();
- } else {
- that.$input.focus();
- autocompleteCall();
- }
- }
- }
-
- function clear() {
- that.$input.val("").focus();
- //autocompleteCall();
- }
-
- function cursor() {
- // fixme: see selection()
- if (arguments.length == 0) {
- return that.$input.$element[0].selectionStart;
- } else {
- that.$input.$element[0].setSelectionRange(arguments[0], arguments[0]);
- }
- }
-
- function focus() {
- var value;
- that.gainFocus();
- that.addClass("OxFocus");
- if (that.$input.is(".OxPlaceholder")) {
- that.$input.val("").removeClass("OxPlaceholder");
- }
- value = that.$input.val();
- if (self.options.autocomplete || self.options.autocorrect || self.options.validate) {
- // fixme: different in webkit and firefox (?), see keyboard handler, need generic function
- $document.bind("keydown", keypress);
- $document.bind("keypress", keypress);
- if (self.options.autocomplete) {
- value !== "" && Ox.isFunction(self.options.autocomplete) ?
- self.options.autocomplete(self.option.id, value, autocompleteCallback) :
- autocomplete(value);
- }
- }
- }
-
- function keypress(event) {
- if (event.keyCode != 13) {
- setTimeout(function() {
- var value = that.$input.val();
- if (value != self.value) {
- self.value = value;
- self.options.autocomplete && autocompleteCall();
- self.options.autocorrect && autocorrect();
- self.options.validate && validateCall();
- }
- }, 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());
- }
-
- function validate() {
- var value = that.$input.val(),
- valid = self.options.validate(value) != null;
- validateCallback({
- valid: valid,
- message: "Invalid " + self.options.label
+ function change() {
+ self.options.value = self.$input.val();
+ that.triggerEvent("change", {
+ value: self.options.value
});
}
- function validateCall() {
- var value = that.$input.val();
- Ox.print("validate call", value)
- if (self.options.validate) {
- if (value !== "") {
- Ox.isFunction(self.options.validate) ?
- self.options.validate(value, validateCallback) :
- validate(value);
+ function clear() {
+ // fixme: set to min, not zero
+ // fixme: make this work for password
+ var value = "";
+ if (self.options.type == "float") {
+ value = "0.0";
+ } else if (self.options.type == "integer") {
+ value = "0"
+ }
+ self.$input.val(value);
+ cursor(0, value.length);
+ }
+
+ function clickArrow(i) {
+ self.options.value = Ox.limit(
+ parseFloat(self.options.value) + (i == 0 ? -1 : 1) * self.options.arrowStep,
+ self.options.min,
+ self.options.max
+ );
+ self.$input.val(self.options.value);//.focus();
+ }
+
+ function clickMenu(event, data) {
+ Ox.print("clickMenu", data);
+ self.options.value = data.title;
+ self.$input.val(self.options.value).focus();
+ that.gainFocus();
+ self.options.autocompleteSelectSubmit && submit();
+ }
+
+ function cursor(start, end) {
+ /*
+ cursor() returns [start, end]
+ cursor(start) sets start
+ cursor([start, end]) sets start and end
+ cursor(start, end) sets start and end
+ */
+ var isArray = Ox.isArray(start);
+ if (arguments.length == 0) {
+ return [self.$input[0].selectionStart, self.$input[0].selectionEnd];
+ } else {
+ end = isArray ? start[1] : (end ? end : start);
+ start = isArray ? start[0] : start;
+ self.$input[0].setSelectionRange(start, end);
+ }
+ }
+
+ function deselectMenu() {
+ self.options.value = self.oldValue;
+ self.$input.val(self.options.value);
+ cursor(self.oldCursor);
+ }
+
+ function focus() {
+ Ox.print("focus()")
+ if (
+ that.hasClass("OxFocus") || // fixme: this is just a workaround, since for some reason, focus() gets called twice on focus
+ (self.$autocompleteMenu && self.$autocompleteMenu.is(":visible")) ||
+ (self.hasPasswordPlaceholder && self.$input.is(":visible"))
+ ) {
+ return;
+ }
+ that.gainFocus();
+ self.options.placeholder && setPlaceholder();
+ if (self.bindKeyboard) {
+ Ox.print("binding...")
+ // fixme: different in webkit and firefox (?), see keyboard handler, need generic function
+ $document.keydown(keypress);
+ $document.keypress(keypress);
+ self.options.autocompleteSelect && setTimeout(autocomplete, 0); // fixme: why is the timeout needed?
+ }
+ }
+
+ function getInputWidth() {
+ return self.options.width - 14 -
+ (self.options.arrows ? 32 : 0) -
+ (self.options.clear ? 16 : 0) -
+ (self.options.label ? self.options.labelWidth : 0);
+ }
+
+ function keypress(event) {
+ var oldCursor = cursor(),
+ oldValue = self.options.value,
+ newValue = oldValue.substr(0, oldCursor[0] - 1),
+ hasDeletedSelectedEnd = (event.keyCode == 8 || event.keyCode == 46) &&
+ oldCursor[0] < oldCursor[1] && oldCursor[1] == oldValue.length;
+ Ox.print("keypress", event.keyCode)
+ if (event.keyCode != 9 && event.keyCode != 13 && event.keyCode != 27) { // fixme: can't 13 and 27 return false?
+ setTimeout(function() { // wait for val to be set
+ var value = self.$input.val();
+ if (self.options.autocompleteReplaceCorrect && hasDeletedSelectedEnd) {
+ Ox.print(value, "->", newValue);
+ value = newValue; // value.substr(0, value.length - 1);
+ self.$input.val(value);
+ }
+ if (value != self.options.value) {
+ self.options.value = value;
+ self.options.autocomplete && autocomplete(oldValue, oldCursor);
+ self.options.autovalidate && autovalidate(oldValue, oldCursor);
+ }
+ }, 0);
+ }
+ if ((event.keyCode == 38 || event.keyCode == 40) && self.options.autocompleteSelect && self.$autocompleteMenu.is(":visible")) {
+ return false;
+ }
+ }
+
+ function selectMenu(event, data) {
+ var pos = cursor();
+ Ox.print("selectMenu", pos)
+ self.options.value = data.title
+ self.$input.val(self.options.value);
+ cursor(pos[0], self.options.value.length)
+ }
+
+ function setPlaceholder() {
+ if (self.options.placeholder) {
+ if (that.hasClass("OxFocus")) {
+ if (self.options.value === "") {
+ if (self.options.type == "password") {
+ self.$placeholder.hide();
+ self.$input.show().focus();
+ } else {
+ self.$input
+ .removeClass("OxPlaceholder")
+ .val("");
+ }
+ }
} else {
- validateCallback({
- valid: false,
- message: ""
- });
+ if (self.options.value === "") {
+ if (self.options.type == "password") {
+ self.$input.hide();
+ self.$placeholder.show();
+ } else {
+ self.$input
+ .addClass("OxPlaceholder")
+ .val(self.options.placeholder)
+ }
+ } else {
+ self.$input
+ .removeClass("OxPlaceholder")
+ .val(self.options.value)
+ }
}
}
}
- function validateCallback(data) {
- if (data.valid != self.valid) {
- self.message = data.message;
- self.valid = data.valid;
- that.triggerEvent("validate", data);
+ function setWidth() {
+
+ }
+
+ function submit() {
+ self.$input.blur();
+ that.triggerEvent("submit", {
+ value: self.options.value
+ });
+ }
+
+ self.onChange = function(key, value) {
+ var inputWidth, val;
+ if (key == "value") {
+ val = self.$input.val();
+ self.$input.val(value);
+ setPlaceholder();
+ } else if (key == "width") {
+ inputWidth = getInputWidth();
+ self.$input.css({
+ width: inputWidth + "px"
+ });
+ self.hasPasswordPlaceholder && self.$placeholder.css({
+ width: inputWidth + "px"
+ });
+ }
+ };
+
+ that.focus = function() {
+ self.$input.focus();
+ cursor(0, self.$input.val().length);
+ };
+
+ return that;
+
+ };
+
+ Ox.AutocorrectIntFunction = function(min, max, pad, year) {
+ var pad = pad || false,
+ year = year || false,
+ maxLength = max.toString().length,
+ ret = null,
+ values = [];
+ $.each(Ox.range(min, max + 1), function(i, v) {
+ values.push(v + "");
+ pad && v.toString().length < maxLength && values.push(Ox.pad(v, maxLength));
+ });
+ return function(value, blur, callback) {
+ var results;
+ if (year && value == "1") {
+ value = "1900";
+ } else {
+ results = Ox.find(values, value);
+ value = results[0].length == 1 && results[0][0].length < maxLength ?
+ (pad ? Ox.pad(results[0][0], maxLength) : results[0][0]) :
+ (results[0].length ? results[0][0] : null);
+ }
+ callback(value);
+ };
+ };
+
+ Ox.InputGroup = function(options, self) {
+
+ /***
+ Ox.InputGroup
+ Options:
+ Methods:
+ Events:
+ ***/
+
+ var self = self || {},
+ that = new Ox.Element("div", self)
+ .defaults({
+ id: "",
+ inputs: [],
+ separators: [],
+ width: 0
+ })
+ .options(options || {})
+ .addClass("OxInputGroup")
+ .click(click);
+
+ if (self.options.width) {
+ setWidths();
+ } else {
+ self.options.width = getWidth();
+ }
+ that.css({
+ width: self.options.width + "px"
+ });
+
+ $.extend(self, {
+ //$input: [],
+ $separator: []
+ });
+
+ $.each(self.options.separators, function(i, v) {
+ self.$separator[i] = new Ox.Label({
+ textAlign: "center",
+ title: v.title,
+ width: v.width + 32
+ })
+ .addClass("OxSeparator")
+ .css({
+ marginLeft: (self.options.inputs[i].options("width") - (i == 0 ? 16 : 32)) + "px"
+ })
+ .appendTo(that);
+ });
+
+ $.each(self.options.inputs, function(i, $input) {
+ $input.options({
+ id: self.options.id + Ox.toTitleCase($input.options("id")),
+ parent: that
+ })
+ .css({
+ marginLeft: -Ox.sum($.map(self.options.inputs, function(v_, i_) {
+ return i_ > i ? self.options.inputs[i_ - 1].options("width") +
+ self.options.separators[i_ - 1].width : (i_ == i ? 16 : 0);
+ })) + "px"
+ })
+ .bindEvent({
+ change: change,
+ submit: change
+ })
+ .appendTo(that);
+ });
+
+ function change(event, data) {
+ Ox.print("InputGroup change")
+ // fixme: would be good to pass a value here
+ that.triggerEvent("change");
+ }
+
+ function click(event) {
+ if ($(event.target).hasClass("OxSeparator")) {
+ self.options.inputs[0].focus();
}
}
- that.changeLabel = function(id) {
- that.$label.html(Ox.getObjectById(self.options.label, id).title);
- self.selectMenu.checkItem(id);
+ function getWidth() {
+ return Ox.sum($.map(self.options.inputs, function(v, i) {
+ return v.options("width");
+ })) + Ox.sum($.map(self.options.separators, function(v, i) {
+ return v.width;
+ }));
+ }
+
+ function setWidths() {
+ var length = self.options.inputs.length,
+ inputWidths = Ox.divideInt(
+ self.options.width - Ox.sum($.map(self.options.separators, function(v, i) {
+ return v.width;
+ })), length
+ );
+ $.each(self.options.inputs, function(i, v) {
+ v.options({
+ width: inputWidths[1]
+ });
+ });
+ }
+
+ // fixme: is this used?
+ that.getInputById = function(id) {
+ var input = null;
+ $.each(self.options.inputs, function(i, v) {
+ Ox.print(v, v.options("id"), id)
+ if (v.options("id") == self.options.id + Ox.toTitleCase(id)) {
+ input = v;
+ return false;
+ }
+ });
+ return input;
};
- that.height = function(value) {
+ return that;
+
+ };
+
+ Ox.ColorInput = function(options, self) {
+
+ var self = $.extend(self || {}, {
+ options: $.extend({
+ id: "",
+ value: "0, 0, 0"
+ }, options)
+ }),
+ that;
+
+ self.values = self.options.value.split(", ");
+ self.$inputs = [];
+ $.each(["red", "green", "blue"], function(i, v) {
+ self.$inputs[i] = new Ox.Input({
+ id: v,
+ max: 255,
+ type: "integer",
+ value: self.values[i],
+ width: 36
+ })
+ .bindEvent("autovalidate", change);
+ });
+ self.$inputs[3] = new Ox.Label({
+ id: "color",
+ width: 36
+ })
+ .css({
+ background: "rgb(" + self.options.value + ")"
+ });
+ self.$inputs[4] = new Ox.ColorPicker({
+ id: "picker"
+ })
+ .bindEvent("change", function(event, data) {
+ Ox.print("change function called");
+ self.options.value = data.value;
+ self.values = data.value.split(", ");
+ $.each(Ox.range(3), function(i) {
+ self.$inputs[i].options({
+ value: self.values[i]
+ });
+ });
+ })
+ .options({
+ width: 16 // this is just a hack to make the InputGroup layout work
+ });
+
+ that = new Ox.InputGroup({
+ id: self.options.id,
+ inputs: self.$inputs,
+ separators: [
+ {title: ",", width: 8},
+ {title: ",", width: 8},
+ {title: "", width: 8},
+ {title: "", width: 8}
+ ],
+ value: self.options.value // fixme: it'd be nicer if this would be taken care of by passing self
+ }, self)
+ .bindEvent("change", change);
+
+ function change() {
+ self.options.value = $.map(self.$inputs, function(v, i) {
+ return v.options("value");
+ }).join(", ");
+ self.$inputs[3].css({
+ background: "rgb(" + self.options.value + ")"
+ });
+ }
+
+ return that;
+
+ };
+
+ Ox.DateInput = function(options, self) {
+
+ var self = $.extend(self || {}, {
+ options: $.extend({
+ format: "short",
+ value: Ox.formatDate(new Date(), "%F"),
+ weekday: false,
+ width: {
+ day: 32,
+ month: options.format == "long" ? 80 : (options.format == "medium" ? 40 : 32),
+ weekday: options.format == "long" ? 80 : 40,
+ year: 48
+ }
+ }, options)
+ }),
+ that;
+
+ $.extend(self, {
+ date: new Date(self.options.value.replace(/-/g, "/")),
+ formats: {
+ day: "%d",
+ month: self.options.format == "short" ? "%m" :
+ (self.options.format == "medium" ? "%b" : "%B"),
+ weekday: self.options.format == "long" ? "%A" : "%a",
+ year: "%Y"
+ },
+ months: self.options.format == "long" ? Ox.MONTHS : $.map(Ox.MONTHS, function(v, i) {
+ return v.substr(0, 3);
+ }),
+ weekdays: self.options.format == "long" ? Ox.WEEKDAYS : $.map(Ox.WEEKDAYS, function(v, i) {
+ return v.substr(0, 3);
+ })
+ });
+
+ self.$input = $.extend(self.options.weekday ? {
+ weekday: new Ox.Input({
+ autocomplete: self.weekdays,
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "weekday",
+ value: Ox.formatDate(self.date, self.formats.weekday),
+ width: self.options.width.weekday
+ })
+ .bindEvent("autocomplete", changeWeekday),
+ } : {}, {
+ day: new Ox.Input({
+ autocomplete: $.map(Ox.range(1, Ox.getDaysInMonth(
+ parseInt(Ox.formatDate(self.date, "%Y"), 10),
+ parseInt(Ox.formatDate(self.date, "%m"), 10)
+ ) + 1), function(v, i) {
+ return self.options.format == "short" ? Ox.pad(v, 2) : v.toString();
+ }),
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "day",
+ value: Ox.formatDate(self.date, self.formats.day),
+ textAlign: "right",
+ width: self.options.width.day
+ })
+ .bindEvent("autocomplete", changeDay),
+ month: new Ox.Input({
+ autocomplete: self.options.format == "short" ? $.map(Ox.range(1, 13), function(v, i) {
+ return Ox.pad(v, 2);
+ }) : self.months,
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "month",
+ value: Ox.formatDate(self.date, self.formats.month),
+ textAlign: self.options.format == "short" ? "right" : "left",
+ width: self.options.width.month
+ })
+ .bindEvent("autocomplete", changeMonthOrYear),
+ year: new Ox.Input({
+ autocomplete: $.map($.merge(Ox.range(1900, 3000), Ox.range(1000, 1900)), function(v, i) {
+ return v.toString();
+ }),
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "year",
+ value: Ox.formatDate(self.date, self.formats.year),
+ textAlign: "right",
+ width: self.options.width.year
+ })
+ .bindEvent("autocomplete", changeMonthOrYear)
+ });
+
+ that = new Ox.InputGroup($.extend(self.options, {
+ id: self.options.id,
+ inputs: $.merge(self.options.weekday ? [
+ self.$input.weekday
+ ] : [], self.options.format == "short" ? [
+ self.$input.year, self.$input.month, self.$input.day
+ ] : [
+ self.$input.month, self.$input.day, self.$input.year
+ ]),
+ separators: $.merge(self.options.weekday ? [
+ {title: self.options.format == "short" ? "" : ",", width: 8},
+ ] : [], self.options.format == "short" ? [
+ {title: "-", width: 8}, {title: "-", width: 8}
+ ] : [
+ {title: "", width: 8}, {title: ",", width: 8}
+ ]),
+ width: 0
+ }), self);
+
+ Ox.print("SELF", self)
+
+ function changeDay() {
+ self.options.weekday && self.$input.weekday.options({
+ value: Ox.formatDate(new Date([
+ self.$input.month.options("value"),
+ self.$input.day.options("value"),
+ self.$input.year.options("value")
+ ].join(" ")), self.formats.weekday)
+ });
+ setValue();
+ }
+
+ function changeMonthOrYear() {
+ var day = self.$input.day.options("value"),
+ month = self.$input.month.options("value"),
+ year = self.$input.year.options("value"),
+ days = Ox.getDaysInMonth(year, self.options.format == "short" ? parseInt(month, 10) : month);
+ day = day <= days ? day : days;
+ Ox.print(year, month, "day days", day, days)
+ self.options.weekday && self.$input.weekday.options({
+ value: Ox.formatDate(new Date([month, day, year].join(" ")), self.formats.weekday)
+ });
+ self.$input.day.options({
+ autocomplete: $.map(Ox.range(1, days + 1), function(v, i) {
+ return self.options.format == "short" ? Ox.pad(v, 2) : v.toString();
+ }),
+ value: self.options.format == "short" ? Ox.pad(day, 2) : day.toString()
+ });
+ setValue();
+ }
+
+ function changeWeekday() {
+ var date = getDateInWeek(
+ self.$input.weekday.options("value"),
+ self.$input.month.options("value"),
+ self.$input.day.options("value"),
+ self.$input.year.options("value")
+ );
+ self.$input.month.options({value: date.month});
+ self.$input.day.options({
+ autocomplete: $.map(Ox.range(1, Ox.getDaysInMonth(date.year, date.month) + 1), function(v, i) {
+ return self.options.format == "short" ? Ox.pad(v, 2) : v.toString();
+ }),
+ value: date.day
+ });
+ self.$input.year.options({value: date.year});
+ setValue();
+ }
+
+ function getDateInWeek(weekday, month, day, year) {
+ Ox.print([month, day, year].join(" "))
+ var date = new Date([month, day, year].join(" "));
+ date = Ox.getDateInWeek(date, weekday);
+ return {
+ day: Ox.formatDate(date, self.formats.day),
+ month: Ox.formatDate(date, self.formats.month),
+ year: Ox.formatDate(date, self.formats.year)
+ };
+ }
+
+ function setValue() {
+ self.options.value = Ox.formatDate(new Date(self.options.format == "short" ? [
+ self.$input.year.options("value"),
+ self.$input.month.options("value"),
+ self.$input.day.options("value")
+ ].join("/") : [
+ self.$input.month.options("value"),
+ self.$input.day.options("value"),
+ self.$input.year.options("value")
+ ].join(" ")), "%F");
+ }
+
+ /*
+ function normalize() {
+ var year = that.getInputById("year").options("value"),
+ month = that.getInputById("month").options("value"),
+ day = that.getInputById("day").options("value")
+ return {
+ year: year,
+ month: self.options.format == "short" ? month :
+ Ox.pad((format == "medium" ? Ox.WEEKDAYS.map(function(v, i) {
+ return v.substr(0, 3);
+ }) : Ox.WEEKDAYS).indexOf(month), 2),
+ day: Ox.pad(day, 2)
+ }
+ }
+ */
+
+ /*
+ that.serialize = function() {
+ var normal = normalize();
+ return [normal.year, normal.month, normal.day].join("-");
+ }
+ */
+
+ return that;
+
+ };
+
+ Ox.DateTimeInput = function(options, self) {
+
+ var self = self || {},
+ that = new Ox.Element({}, self)
+ .defaults({
+ ampm: false,
+ format: "short",
+ seconds: false,
+ value: Ox.formatDate(new Date(), "%F %T"),
+ weekday: false
+ })
+ .options(options || {});
+
+ self.values = self.options.value.split(" ");
+ Ox.print(self.values)
+
+ that = new Ox.InputGroup({
+ inputs: [
+ new Ox.DateInput({
+ format: self.options.format,
+ id: "date",
+ value: self.values[0],
+ weekday: self.options.weekday
+ }),
+ new Ox.TimeInput({
+ ampm: self.options.ampm,
+ id: "time",
+ value: self.values[1],
+ seconds: self.options.seconds
+ })
+ ],
+ separators: [
+ {title: "", width: 8}
+ ],
+ value: self.options.value
+ })
+ .bindEvent("change", setValue);
+
+ function setValue() {
+ self.options.value = [
+ self.options("inputs")[0].options("value"),
+ self.options("inputs")[1].options("value")
+ ].join(" ");
+ }
+
+ return that;
+
+ };
+
+ Ox.PlaceInput = function(options, self) {
+
+ var self = $.extend(self || {}, {
+ options: $.extend({
+ id: "",
+ value: "United States"
+ }, options)
+ }),
+ that;
+
+ that = new Ox.FormElementGroup({
+ id: self.options.id,
+ elements: [
+ new Ox.Input({
+ id: "input",
+ value: self.options.value
+ }),
+ new Ox.PlacePicker({
+ id: "picker",
+ overlap: "left",
+ value: self.options.value
+ })
+ ],
+ float: "right"
+ }, self)
+ .bindEvent("change", change);
+
+ function change() {
+
+ }
+
+ return that;
+
+ };
+
+ Ox.TimeInput = function(options, self) {
+
+ // fixme: seconds get set even if options.seconds is false
+ var self = self || {},
+ that = new Ox.Element({}, self)
+ .defaults({
+ ampm: false,
+ seconds: false,
+ milliseconds: false,
+ value: Ox.formatDate(new Date(), "%T"),
+ })
+ .options(options || {});
+
+ if (self.options.milliseconds) {
+ self.options.seconds = true;
+ if (self.options.value.indexOf(".") == -1) {
+ self.options.value += ".000";
+ }
+ }
+
+ self.date = getDate();
+ self.values = getValues();
+
+ self.$input = {
+ hours: Ox.Input({
+ autocomplete: $.map(self.options.ampm ? Ox.range(1, 13) : Ox.range(0, 24), function(v) {
+ return Ox.pad(v, 2);
+ }),
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "hours",
+ textAlign: "right",
+ value: self.values.hours,
+ width: 32
+ }),
+ minutes: Ox.Input({
+ autocomplete: $.map(Ox.range(0, 60), function(v) {
+ return Ox.pad(v, 2);
+ }),
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "minutes",
+ textAlign: "right",
+ value: self.values.minutes,
+ width: 32
+ }),
+ seconds: Ox.Input({
+ autocomplete: $.map(Ox.range(0, 60), function(v) {
+ return Ox.pad(v, 2);
+ }),
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "seconds",
+ textAlign: "right",
+ value: self.values.seconds,
+ width: 32
+ }),
+ milliseconds: Ox.Input({
+ autocomplete: $.map(Ox.range(0, 1000), function(v) {
+ return Ox.pad(v, 3);
+ }),
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "milliseconds",
+ textAlign: "right",
+ value: self.values.milliseconds,
+ width: 40
+ }),
+ ampm: Ox.Input({
+ autocomplete: ["AM", "PM"],
+ autocompleteReplace: true,
+ autocompleteReplaceCorrect: true,
+ id: "ampm",
+ value: self.values.ampm,
+ width: 32
+ })
+ };
+
+ that = new Ox.InputGroup($.extend(self.options, {
+ inputs: $.merge($.merge($.merge([
+ self.$input.hours,
+ self.$input.minutes,
+ ], self.options.seconds ? [
+ self.$input.seconds
+ ] : []), self.options.milliseconds ? [
+ self.$input.milliseconds
+ ] : []), self.options.ampm ? [
+ self.$input.ampm
+ ] : []),
+ separators: $.merge($.merge($.merge([
+ {title: ":", width: 8},
+ ], self.options.seconds ? [
+ {title: ":", width: 8}
+ ] : []), self.options.milliseconds ? [
+ {title: ".", width: 8}
+ ] : []), self.options.ampm ? [
+ {title: "", width: 8}
+ ] : []),
+ //width: self.options.width || 128
+ }), self)
+ .bindEvent("change", setValue);
+
+ setValue();
+
+ function getDate() {
+ return new Date("1970/01/01 " + (
+ self.options.milliseconds ?
+ self.options.value.substr(0, self.options.value.length - 4) :
+ self.options.value
+ ));
+ }
+
+ function getValues() {
+ self.date = getDate();
+ return {
+ ampm: Ox.formatDate(self.date, "%p"),
+ hours: Ox.formatDate(self.date, self.options.ampm ? "%I" : "%H"),
+ milliseconds: self.options.milliseconds ? self.options.value.substr(-3) : "000",
+ minutes: Ox.formatDate(self.date, "%M"),
+ seconds: Ox.formatDate(self.date, "%S")
+ };
+ }
+
+ function setValue() {
+ self.options.value = Ox.formatDate(new Date("1970/01/01 " + [
+ self.$input.hours.options("value"),
+ self.$input.minutes.options("value"),
+ self.options.seconds ? self.$input.seconds.options("value") : "00"
+ ].join(":") + (self.options.ampm ? " " + self.$input.ampm.options("value") : "")),
+ (self.options.seconds? "%T" : "%H:%M")) +
+ (self.options.milliseconds ? "." + self.$input.milliseconds.options("value") : "");
+ Ox.print("SETVALUE", self.options.value);
+ }
+
+ function setValues() {
+ self.values = getValues();
+ $.each(self.$input, function(k, v) {
+ self.$input[k].options({
+ value: self.values[k]
+ });
+ });
+ }
+
+ self.onChange = function(key, value) {
+ if (key == "value") {
+ setValues();
+ }
+ }
+
+ return that;
+
+ };
+
+ Ox.Label = function(options, self) {
+
+ var self = self || {},
+ that = new Ox.Element("div", self)
+ .defaults({
+ disabled: false,
+ id: "",
+ overlap: "none",
+ textAlign: "left",
+ title: "",
+ width: "auto"
+ })
+ .options(options)
+ .addClass(
+ "OxLabel" + (self.options.disabled ? " OxDisabled" : "") +
+ (self.options.overlap != "none" ?
+ " OxOverlap" + Ox.toTitleCase(self.options.overlap) : "")
+ )
+ .css($.extend(self.options.width == "auto" ? {} : {
+ width: (self.options.width - 14) + "px"
+ }, {
+ textAlign: self.options.textAlign
+ }))
+ .html(self.options.title);
+
+ return that;
+
+ };
+
+ Ox.OptionGroup = function(items, min, max, property) {
+
+ /*
+ to be used by ButtonGroup, CheckboxGroup, Select and Menu
+ */
+
+ var property = property || "checked"
+ length = items.length,
+ max = max == -1 ? length : max;
+
+ function getLastBefore(pos) {
+ // returns the position of the last checked item before position pos
+ var last = -1;
+ Ox.print(items, items.length, length, $.merge(
+ pos > 0 ? Ox.range(pos - 1, -1, -1) : [],
+ pos < length - 1 ? Ox.range(length - 1, pos, -1) : []
+ ))
+ $.each($.merge(
+ pos > 0 ? Ox.range(pos - 1, -1, -1) : [],
+ pos < length - 1 ? Ox.range(length - 1, pos, -1) : []
+ ), function(i, v) {
+ Ox.print(pos, v)
+ if (items[v][property]) {
+ last = v;
+ return false;
+ }
+ });
+ return last;
+ }
+
+ function getNumber() {
+ // returns the number of checked items
+ var num = 0;
+ $.each(items, function(i, item) {
+ if (item[property]) {
+ num++;
+ }
+ })
+ return num;
+ }
+
+ this[property] = function() {
+ // returns an array with the positions of all checked item
+ var checked = [];
+ $.each(items, function(i, item) {
+ if (item[property]) {
+ checked.push(i);
+ }
+ })
+ return checked;
+ };
+
+ this.init = function() {
+ var num = getNumber(),
+ count = 0;
+ //if (num < min || num > max) {
+ $.each(items, function(i, item) {
+ if (Ox.isUndefined(item[property])) {
+ item[property] = false;
+ }
+ if (item[property]) {
+ count++;
+ if (count > max) {
+ item[property] = false;
+ }
+ } else {
+ if (num < min) {
+ item[property] = true;
+ num++;
+ }
+ }
+ });
+ //}
+ return items;
+ };
+
+ this.toggle = function(pos) {
+ var last,
+ num = getNumber(),
+ toggled = [];
+ if (!items[pos][property]) { // check
+ if (num >= max) {
+ last = getLastBefore(pos);
+ items[last][property] = false;
+ toggled.push(last);
+ }
+ if (!items[pos][property]) {
+ items[pos][property] = true;
+ toggled.push(pos);
+ }
+ } else { // uncheck
+ if (num > min) {
+ items[pos][property] = false;
+ toggled.push(pos);
+ }
+ }
+ return toggled;
+ }
+
+ return this;
+
+ }
+
+ Ox.Range = function(options, self) {
+
+ /***
+ Ox.Range
+ Options:
+ 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
+ trackGradient array colors
+ 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
+ valueNames array value names to display on thumb
+ ***/
+
+ var self = self || {},
+ that = new Ox.Element({}, self)
+ .defaults({
+ arrows: false,
+ arrowStep: 1,
+ arrowSymbols: ["previous", "next"],
+ max: 100,
+ min: 0,
+ orientation: "horizontal",
+ step: 1,
+ size: 128,
+ thumbSize: 16,
+ thumbValue: false,
+ trackColors: [],
+ trackImages: [],
+ trackStep: 0,
+ value: 0,
+ valueNames: null,
+ })
+ .options($.extend(options, {
+ arrowStep: options.arrowStep ?
+ options.arrowStep : options.step,
+ trackImages: $.makeArray(options.trackImages || [])
+ }))
+ .addClass("OxRange")
+ .css({
+ width: self.options.size + "px"
+ });
+
+ $.extend(self, {
+ trackColors: self.options.trackColors.length,
+ trackImages: self.options.trackImages.length,
+ trackSize: self.options.size - self.options.arrows * 32,
+ values: (self.options.max - self.options.min + self.options.step) /
+ self.options.step
+ });
+ $.extend(self, {
+ thumbSize: Math.max(self.trackSize / self.values, self.options.thumbSize),
+ trackImageWidths: self.trackImages == 1 ? [self.trackSize - 16] :
+ Ox.divideInt(self.trackSize - 2, self.trackImages)
+ });
+ $.extend(self, {
+ trackColorsStart: self.thumbSize / 2 / self.options.size,
+ trackColorsStep: (self.options.size - self.thumbSize) / (self.trackColors - 1) / self.options.size
+ });
+
+ if (self.options.arrows) {
+ self.$arrows = [];
+ $.each(Ox.range(0, 2), function(i) {
+ self.$arrows[i] = Ox.Button({
+ overlap: i == 0 ? "right" : "left",
+ title: self.options.arrowSymbols[i],
+ type: "image"
+ })
+ .addClass("OxArrow")
+ .mousedown(function(e) {
+ clickArrow(e, i);
+ })
+ .appendTo(that.$element);
+ });
+ }
+
+ self.$track = $("
")
+ .addClass("OxTrack")
+ .css($.extend({
+ width: (self.trackSize - 2) + "px"
+ }, self.trackImages == 1 ? {
+ background: "rgb(0, 0, 0)"
+ } : {}))
+ .mousedown(clickTrack)
+ .appendTo(that.$element);
+
+ self.trackColors && setTrackColors();
+
+ if (self.trackImages) {
+ self.$trackImages = $("
")
+ .css({
+ width: self.trackSize + "px",
+ marginRight: (-self.trackSize - 1) + "px"
+ })
+ .appendTo(self.$track);
+ $.each(self.options.trackImages, function(i, v) {
+ Ox.print(self.trackImageWidths[i])
+ $("
![]()
")
+ .attr({
+ src: v
+ })
+ .addClass(i == 0 ? "OxFirstChild" : "")
+ .addClass(i == self.trackImages - 1 ? "OxLastChild" : "")
+ .css({
+ width: self.trackImageWidths[i] + "px"
+ })
+ .mousedown(function(e) {
+ e.preventDefault(); // prevent drag
+ })
+ .appendTo(self.$trackImages);
+ //left += self.trackImageWidths[i];
+ });
+ }
+
+ self.$thumb = Ox.Button({
+ id: self.options.id + "Thumb",
+ title: self.options.thumbValue ? (self.options.valueNames ?
+ self.options.valueNames[self.options.value] :
+ self.options.value) : "",
+ width: self.thumbSize
+ })
+ .addClass("OxThumb")
+ /*
+ .css({
+ border: "1px solid rgb(255, 255, 255)",
+ background: "rgba(0, 0, 0, 0)"
+ })
+ */
+ .appendTo(self.$track);
+
+ setThumb();
+
+ function clickArrow(e, i) {
+ // fixme: shift doesn't work, see menu scrolling
+ var interval,
+ timeout = setTimeout(function() {
+ interval = setInterval(function() {
+ setValue(self.options.value + self.options.arrowStep * (i == 0 ? -1 : 1));
+ }, 50);
+ }, 500);
+ setValue(self.options.value + self.options.arrowStep * (i == 0 ? -1 : 1) * (e.shiftKey ? 2 : 1), true);
+ $window.one("mouseup", function() {
+ clearInterval(interval);
+ clearTimeout(timeout);
+ });
+ }
+
+ function clickTrack(e) {
+ //Ox.Focus.focus();
+ var isThumb = $(e.target).hasClass("OxThumb"),
+ left = self.$track.offset().left,
+ offset = isThumb ? e.clientX - self.$thumb.offset().left - 8 /*self.thumbSize / 2*/ : 0;
+ setValue(val(e), !isThumb);
+ $window.mousemove(function(e) {
+ setValue(val(e));
+ });
+ $window.one("mouseup", function() {
+ $window.unbind("mousemove");
+ });
+ function val(e) {
+ return getVal(e.clientX - left - offset);
+ }
+ }
+
+ function getPx(val) {
+ var pxPerVal = (self.trackSize - self.thumbSize) /
+ (self.options.max - self.options.min);
+ return Math.ceil((val - self.options.min) * pxPerVal);
+ }
+
+ /*
+ function getTime(oldValue, newValue) {
+ return self.animationTime * Math.abs(oldValue - newValue) / (self.options.max - self.options.min);
+ }
+ */
+
+ function getVal(px) {
+ var px = self.trackSize / self.values >= 16 ? px : px - 8,
+ valPerPx = (self.options.max - self.options.min) /
+ (self.trackSize - self.thumbSize);
+ return Ox.limit(self.options.min +
+ Math.floor(px * valPerPx / self.options.step) * self.options.step,
+ self.options.min, self.options.max);
+ }
+
+ function setThumb(animate) {
+ self.$thumb.stop().animate({
+ marginLeft: (getPx(self.options.value) - 1) + "px",
+ //width: self.thumbSize + "px"
+ }, animate ? 200 : 0, function() {
+ if (self.options.thumbValue) {
+ self.$thumb.options({
+ title: self.options.valueNames ?
+ self.options.valueNames[self.options.value] :
+ self.options.value
+ });
+ }
+ });
+ }
+
+ function setTrackColors() {
+ self.$track.css({
+ backgroundImage: $.browser.mozilla ?
+ ("-moz-linear-gradient(left, " +
+ self.options.trackColors[0] + " 0%, " + $.map(self.options.trackColors, function(v, i) {
+ return v + " " + ((self.trackColorsStart + self.trackColorsStep * i) * 100) + "%";
+ }).join(", ") + ", " + self.options.trackColors[self.trackColors - 1] + " 100%)") :
+ ("-webkit-gradient(linear, left top, right top, color-stop(0, " +
+ self.options.trackColors[0] + "), " + $.map(self.options.trackColors, function(v, i) {
+ return "color-stop(" + (self.trackColorsStart + self.trackColorsStep * i) + ", " + v + ")";
+ }).join(", ") + ", color-stop(1, " + self.options.trackColors[self.trackColors - 1] + "))")
+ });
+ }
+
+ function setValue(value, animate) {
+ var value = Ox.limit(value, self.options.min, self.options.max);
+ if (value != self.options.value) {
+ //time = getTime(self.options.value, value);
+ self.options.value = value;
+ setThumb(animate);
+ that.triggerEvent("change", {
+ value: value
+ });
+ }
+ }
+
+ self.onChange = function(key, value) {
+ if (key == "trackColors") {
+ setTrackColors();
+ } else if (key == "value") {
+ setThumb();
+ }
+ }
+
+ return that;
+
+ };
+
+ 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: [],
+ max: 1,
+ min: 1,
+ overlap: "none", // can be none, left or right
+ selectable: true,
+ size: "medium",
+ title: "",
+ type: "text", // can be "text" or "image"
+ width: "auto"
+ })
+ .options(options)
+ .addClass(
+ "OxSelect Ox" + Ox.toTitleCase(self.options.size) +
+ (self.options.overlap == "none" ? "" : " OxOverlap" +
+ Ox.toTitleCase(self.options.overlap))
+ )
+ .css(self.options.width == "auto" ? {} : {
+ width: self.options.width + "px"
+ });
+
+ $.extend(self, {
+ buttonId: self.options.id + "Button",
+ groupId: self.options.id + "Group",
+ menuId: self.options.id + "Menu"
+ });
+
+ if (self.options.selectable) {
+ self.optionGroup = new Ox.OptionGroup(
+ self.options.items,
+ self.options.min,
+ self.options.max
+ );
+ self.options.items = self.optionGroup.init();
+ self.checked = self.optionGroup.checked();
+ }
+
+ if (self.options.type == "text") {
+ self.$title = $("
")
+ .addClass("OxTitle")
+ .css({
+ width: (self.options.width - 22) + "px"
+ })
+ .html(
+ self.options.title ? self.options.title :
+ self.options.items[self.checked[0]].title
+ )
+ .click(clickButton)
+ .appendTo(that.$element);
+ }
+
+ self.$button = new Ox.Button({
+ id: self.buttonId,
+ style: "symbol",
+ title: "select",
+ type: "image"
+ })
+ .bindEvent("click", clickButton)
+ .appendTo(that);
+
+ self.$menu = new Ox.Menu({
+ element: self.$title || self.$button,
+ id: self.menuId,
+ items: [self.options.selectable ? {
+ group: self.groupId,
+ items: self.options.items,
+ max: self.options.max,
+ min: self.options.min
+ } : self.options.items],
+ side: "bottom",
+ size: self.options.size
+ })
+ .bindEvent("hide", hideMenu);
+
+ if (self.options.selectable) {
+ // fixme: the menu should fire a change event
+ // so we can attach a bindEvent() directly
+ // (may fire one already, but needs to pass group id)
+ Ox.Event.bind(self.groupId, "change", clickMenu);
+ }
+
+ function clickButton() {
+ that.addClass("OxSelected");
+ self.$menu.showMenu();
+ }
+
+ function clickMenu(event, data) {
+ Ox.print("clickMenu: ", self.options.id, data)
+ self.$title && self.$title.html(
+ self.options.title ? self.options.title :
+ data.checked[0].title
+ );
+ that.triggerEvent("change", data);
+ }
+
+ function hideMenu() {
+ that.removeClass("OxSelected");
+ self.$button.removeClass("OxSelected");
+ }
+
+ self.onChange = function(key, value) {
+
+ };
+
+ that.selectItem = function(id) {
+ self.options.type == "text" && self.$title.html(
+ Ox.getObjectById(self.options.items, id).title
+ );
+ self.$menu.checkItem(id);
+ };
+
+ /*
+ that.width = function(val) {
+ // fixme: silly hack, and won't work for css() ... remove!
+ that.$element.width(val + 16);
+ that.$button.width(val);
+ //that.$symbol.width(val);
+ return that;
+ };
+ */
+
+ return that;
+
+ }
+
+ Ox.FormElementGroup = function(options, self) {
+
+ var self = self || {},
+ that = new Ox.Element("div", self)
+ .defaults({
+ id: "",
+ elements: [],
+ float: "left",
+ separators: [],
+ width: 0
+ })
+ .options(options || {})
+ .addClass("OxInputGroup");
+
+ $.each(self.options.float == "left" ? self.options.elements : self.options.elements.reverse(), function(i, $element) {
+ $element.options({
+ id: self.options.id + Ox.toTitleCase($element.options("id")),
+ parent: that
+ })
+ .css({
+ float: self.options.float // fixme: make this a class
+ })
+ .appendTo(that);
+ });
+
+ /*
+ if (self.options.width) {
+ setWidths();
+ } else {
+ self.options.width = getWidth();
+ }
+ that.css({
+ width: self.options.width + "px"
+ });
+ */
+
+ function getWidth() {
+
+ }
+
+ function setWidth() {
+
+ }
+
+ self.onChange = function(key, value) {
+ if (key == "trackColors") {
+
+ }
+ }
+
+ return that;
+
+ }
+
+ Ox.Picker = function(options, self) {
+
+ var self = self || {},
+ that = new Ox.Element("div", self)
+ .defaults({
+ element: null,
+ elementHeight: 128,
+ elementWidth: 256,
+ id: "",
+ overlap: "none"
+ })
+ .options(options || {});
+
+ self.$selectButton = new Ox.Button({
+ overlap: self.options.overlap,
+ title: "select",
+ type: "image"
+ })
+ .click(showMenu)
+ .appendTo(that);
+
+ self.$menu = new Ox.Element("div")
+ .addClass("OxPicker")
+ .css({
+ width: self.options.elementWidth + "px",
+ height: (self.options.elementHeight + 24) + "px"
+ });
+
+ self.options.element
+ .css({
+ width: self.options.elementWidth + "px",
+ height: self.options.elementHeight + "px"
+ })
+ .appendTo(self.$menu);
+
+ self.$bar = new Ox.Bar({
+ orientation: "horizontal",
+ size: 24
+ })
+ .appendTo(self.$menu);
+
+ that.$label = new Ox.Label({
+ width: self.options.elementWidth - 60
+ })
+ .appendTo(self.$bar);
+
+ self.$doneButton = new Ox.Button({
+ title: "Done",
+ width: 48
+ })
+ .click(hideMenu)
+ .appendTo(self.$bar);
+
+ self.$layer = $("
")
+ .addClass("OxLayer")
+ .click(hideMenu);
+
+ function hideMenu() {
+ self.$menu.detach();
+ self.$layer.detach();
+ self.$selectButton
+ .removeClass("OxSelected")
+ .css({
+ MozBorderRadius: "8px",
+ WebkitBorderRadius: "8px"
+ });
+ that.triggerEvent("hide");
+ };
+
+ function showMenu() {
+ var offset = that.offset(),
+ left = offset.left,
+ top = offset.top + 15;
+ self.$selectButton
+ .addClass("OxSelected")
+ .css({
+ MozBorderRadius: "8px 8px 0 0",
+ WebkitBorderRadius: "8px 8px 0 0"
+ });
+ self.$layer.appendTo($body);
+ self.$menu
+ .css({
+ left: left + "px",
+ top: top + "px"
+ })
+ .appendTo($body);
+ that.triggerEvent("show");
+ };
+
+ return that;
+
+ };
+
+ Ox.ColorPicker = function(options, self) {
+
+ var self = self || {},
+ that = new Ox.Element("div", self)
+ .defaults({
+ id: "",
+ value: "0, 0, 0"
+ })
+ .options(options || {});
+
+ Ox.print(self)
+ self.$ranges = [];
+ self.rgb = ["red", "green", "blue"];
+ self.values = self.options.value.split(", ");
+
+ $.each(Ox.range(3), function(i) {
+ self.$ranges[i] = new Ox.Range({
+ arrows: true,
+ id: self.options.id + Ox.toTitleCase(self.rgb[i]),
+ max: 255,
+ size: 328, // 256 + 16 + 40 + 16
+ thumbSize: 40,
+ thumbValue: true,
+ trackColors: getColors(i),
+ value: self.values[i]
+ })
+ .css({
+ position: "absolute",
+ top: (i * 15) + "px"
+ })
+ .bindEvent("change", function(event, data) {
+ change(i, data.value);
+ })
+ .appendTo(that);
+ // fixme: make self.$ranges[i].children() work
+ if (i == 0) {
+ self.$ranges[i].$element.children("input.OxOverlapRight").css({
+ MozBorderRadius: 0,
+ WebkitBorderRadius: 0
+ });
+ self.$ranges[i].$element.children("input.OxOverlapLeft").css({
+ MozBorderRadius: "0 8px 0 0",
+ WebkitBorderRadius: "0 8px 0 0"
+ });
+ } else {
+ self.$ranges[i].$element.children("input").css({
+ MozBorderRadius: 0,
+ WebkitBorderRadius: 0
+ });
+ }
+ });
+
+ that = new Ox.Picker({
+ element: that,
+ elementHeight: 46,
+ elementWidth: 328,
+ id: self.options.id
+ });
+
+ function change(index, value) {
+ self.values[index] = value;
+ self.options.value = self.values.join(", ");
+ that.$label.css({
+ background: "rgb(" + self.options.value + ")"
+ });
+ $.each(Ox.range(3), function(i) {
+ if (i != index) {
+ self.$ranges[i].options({
+ trackColors: getColors(i)
+ });
+ }
+ });
+ that.triggerEvent("change", {
+ value: self.options.value
+ });
+ }
+
+ function getColors(index) {
+ return [
+ "rgb(" + $.map(Ox.range(3), function(v) {
+ return v == index ? 0 : self.values[v];
+ }).join(", ") + ")",
+ "rgb(" + $.map(Ox.range(3), function(v) {
+ return v == index ? 255 : self.values[v];
+ }).join(", ") + ")"
+ ]
+ }
+
+ return that;
+
+ };
+
+ Ox.PlacePicker = function(options, self) {
+
+ var self = $.extend(self || {}, {
+ options: $.extend({
+ id: "",
+ value: "United States"
+ }, options)
+ }),
+ that;
+
+ self.$element = new Ox.Element("div")
+ .css({
+ width: "256px",
+ height: "192px"
+ })
+ .append(
+ self.$topBar = new Ox.Bar({
+ size: 16
+ })
+ .css({
+ MozBorderRadius: "0 8px 0 0",
+ WebkitBorderRadius: "0 8px 0 0"
+ })
+ .append(
+ self.$input = new Ox.Input({
+ clear: true,
+ id: self.options.id + "Input",
+ placeholder: "Find",
+ width: 256
+ })
+ .bindEvent("submit", findPlace)
+ )
+ )
+ .append(
+ self.$container = new Ox.Element("div")
+ .css({
+ width: "256px",
+ height: "160px"
+ })
+ )
+ .append(
+ self.$bottomBar = new Ox.Bar({
+ size: 16
+ })
+ .append(
+ self.$range = new Ox.Range({
+ arrows: true,
+ id: self.options.id + "Range",
+ max: 22,
+ size: 256,
+ thumbSize: 32,
+ thumbValue: true
+ })
+ .bindEvent("change", changeZoom)
+ )
+ );
+
+ self.$input.$element.children("input[type=text]").css({
+ width: "230px",
+ paddingLeft: "2px",
+ MozBorderRadius: "0 8px 8px 0",
+ WebkitBorderRadius: "0 8px 8px 0"
+ });
+ self.$input.$element.children("input[type=image]").css({
+ MozBorderRadius: "0 8px 0 0",
+ WebkitBorderRadius: "0 8px 0 0"
+ });
+ self.$range.$element.children("input").css({
+ MozBorderRadius: 0,
+ WebkitBorderRadius: 0
+ });
+
+ that = new Ox.Picker({
+ element: self.$element,
+ elementHeight: 192,
+ elementWidth: 256,
+ id: self.options.id,
+ overlap: self.options.overlap,
+ value: self.options.value
+ }, self)
+ .bindEvent("show", showPicker);
+
+ that.$label.bind("click", clickLabel)
+
+ self.map = false;
+
+ function changeZoom(event, data) {
+ Ox.print("changeZoom")
+ self.$map.zoom(data.value);
+ }
+
+ function clickLabel() {
+ var name = that.$label.html();
+ if (name) {
+ self.$input.options({
+ value: name
+ })
+ .triggerEvent("submit", {
+ value: name
+ });
+ }
+ }
+
+ function findPlace(event, data) {
+ Ox.print("findPlace", data);
+ self.$map.find(data.value, function(location) {
+ if (location) {
+ that.$label.html(location.name.formatted);
+ }
+ })
+ }
+
+ function onSelect(event, data) {
+ that.$label.html(data.name.formatted);
+ }
+
+ function onZoom(event, data) {
+ self.$range.options({
+ value: data.value
+ });
+ }
+
+ function showPicker() {
+ if (!self.map) {
+ self.$map = new Ox.Map({
+ id: self.options.id + "Map",
+ places: [self.options.value]
+ })
+ .css({
+ width: "256px",
+ height: "160px"
+ })
+ .bindEvent({
+ select: onSelect,
+ zoom: onZoom
+ })
+ .appendTo(self.$container);
+ self.map = true;
+ }
+ }
+
+ return that;
+
+ };
+
+ /*
+ ----------------------------------------------------------------------------
+ delete below
+ ----------------------------------------------------------------------------
+ */
+
+ Ox.Input_ = function(options, self) {
+
+ /*
+ options:
+ clear boolean, clear button, or not
+ disabled boolean, disabled, or not
+ height height (px), if type is "textarea"
+ id
+ label string, or
+ array [{ id, title, checked }] (selectable label) or
+ array [{ id, label: [{ id, title, checked }], width }] (multiple selectable labels)
+ label and placeholder are mutually exclusive
+ labelWidth integer (px)
+ placeholder string, or
+ array [{ id, title, checked }] (selectable placeholder)
+ label and placeholder are mutually exclusive
+ separator string, or
+ array of strings
+ to separate multiple values
+ separatorWidth integer (px), or
+ array of integers
+ serialize function
+ size "large", "medium" or "small"
+ type "password", "select" or "text"
+ unit string, or
+ array [{ id, title, checked }] (selectable unit)
+ unitWidth integer (px)
+ value string, or
+ array [{ id, value, width }] (multiple values)
+ width integer (px)
+ methods:
+ events:
+ */
+
+ var self = self || {},
+ that = new Ox.Element("div", self)
+ .defaults({
+ autocomplete: null,
+ autocorrect: null,
+ autosuggest: null,
+ autosuggestHighlight: false,
+ autosuggestSubmit: false,
+ autovalidate: null,
+ autovalidateName: "Value",
+ clear: false,
+ disabled: false,
+ height: 128,
+ id: "",
+ key: "",
+ label: "",
+ labelWidth: 64,
+ placeholder: "",
+ separator: "",
+ separatorWidth: 16,
+ serialize: null,
+ size: "medium",
+ type: "text",
+ unit: "",
+ unitWidth: 64,
+ value: "",
+ width: 128
+ })
+ .options(options || {})
+ .addClass("OxInput Ox" + Ox.toTitleCase(self.options.size))
+ .css({
+ width: self.options.width + "px"
+ });
+
+ $.extend(self, {
+ clearWidth: 16,
+ hasMultipleKeys: Ox.isArray(self.options.label) && "label" in self.options.label[0],
+ hasMultipleValues: Ox.isArray(self.options.value) &&
+ (self.options.type != "select" || "items" in self.options.value[0]),
+ hasSelectableKeys: Ox.isArray(self.options.label) || Ox.isArray(self.options.placeholder),
+ hasSelectableUnits: Ox.isArray(self.options.unit),
+ keyName: self.options.label ? "label" : (self.options.placeholder ? "placeholder" : ""),
+ placeholderWidth: 16,
+ selectedKey: [0], // fixme: only set on demand?
+ selectedValue: 0,
+ selectedUnit: 0,
+ /* valid: autovalidateCall(true) */
+ });
+
+ $.each(["autocomplete", "autocorrect", "autosuggest", "autovalidate"], function(i, v) {
+ //if (!Ox.isFunction(self.options[v])) {
+ self.options[v] = {
+ "": self.options[v]
+ };
+ //}
+ });
+
+ if (self.keyName && !self.hasMultipleKeys) {
+ self.options[self.keyName] = [$.extend({
+ id: "",
+ label: self.options[self.keyName],
+ }, self.keyName == "label" ? {
+ id: "",
+ width: self.options.labelWidth
+ } : {})];
+ if (!self.hasSelectableKeys) {
+ self.options[self.keyName][0].label = [{
+ id: "",
+ title: self.options[self.keyName][0].label
+ }];
+ }
+ }
+ if (self.hasSelectableKeys) {
+ $.each(self.options[self.keyName], function(keyPos, key) {
+ if (key.width) {
+ self.options.labelWidth = (keyPos == 0 ? 0 : self.options.labelWidth) + key.width;
+ }
+ self.selectedKey[keyPos] = 0;
+ $.each(key, function(valuePos, value) {
+ if (value.checked) {
+ self.selectedKey[keyPos] = valuePos;
+ return false;
+ }
+ });
+ });
+ }
+ self.valueWidth = self.options.width -
+ (self.options.label ? self.options.labelWidth : 0) -
+ ((self.options.placeholder && self.options.placeholder[0].label.length > 1) ? self.placeholderWidth : 0) -
+ (self.options.unit ? self.options.unitWidth : 0) -
+ (self.options.clear ? self.clearWidth : 0);
+ /*
+ if (self.hasMultipleValues) {
+ self.valueWidth -= Ox.isArray(self.options.separatorWidth) ?
+ Ox.sum(self.options.separatorWidth) :
+ (self.options.value.length - 1) * self.options.separatorWidth;
+ }
+ */
+ Ox.print("self.hasMulVal", self.hasMultipleValues);
+ Ox.print("self.options.value", self.options.value)
+ if (!self.hasMultipleValues) {
+ if (self.options.type == "select") {
+ self.options.value = [{
+ id: "",
+ items: self.options.value,
+ width: self.valueWidth
+ }];
+ } else if (self.options.type == "range") {
+ self.options.value = [$.extend({
+ id: "",
+ size: self.valueWidth
+ }, self.options.value)];
+ } else {
+ self.options.value = [{
+ id: "",
+ value: self.options.value,
+ width: self.valueWidth
+ }]
+ }
+ }
+ Ox.print("self.options.value", self.options.value)
+ self.values = self.options.value.length;
+ Ox.print(self.options.id, "self.values", self.values)
+
+ if (Ox.isString(self.options.separator)) {
+ self.options.separator = $.map(new Array(self.values - 1), function(v, i) {
+ return self.options.separator;
+ });
+ }
+ if (Ox.isNumber(self.options.separatorWidth)) {
+ self.options.separatorWidth = $.map(new Array(self.values - 1), function(v, i) {
+ return self.options.separatorWidth;
+ });
+ }
+
+ if (self.options.unit) {
+ if (self.hasSelectableUnits) {
+ $.each(self.options.unit, function(pos, unit) {
+ if (unit.checked) {
+ self.selectedUnit = pos;
+ return false;
+ }
+ });
+ } else {
+ self.options.unit = [{
+ id: "",
+ title: self.options.unit
+ }];
+ }
+ }
+
+ Ox.print("self", self);
+
+ if (self.keyName) {
+ that.$key = [];
+ $.each(self.options[self.keyName], function(keyPos, key) {
+ Ox.print("keyPos key", keyPos, key)
+ if (self.keyName == "label" && key.label.length == 1) {
+ that.$key[keyPos] = new Ox.Label({
+ overlap: "right",
+ title: key.label[0].title,
+ width: self.options.labelWidth
+ })
+ .css({
+ float: "left"
+ })
+ .click(function() {
+ that.$input[0].focus();
+ })
+ .appendTo(that);
+ } else if (key.label.length > 1) {
+ Ox.print("key.length > 1")
+ self.selectKeyId = self.options.id + Ox.toTitleCase(self.keyName) +
+ (self.options[self.keyName].length == 1 ? "" : keyPos);
+ Ox.print("three", self.selectedKey, keyPos, self.selectedKey[keyPos]);
+ that.$key[keyPos] = new Ox.Select({
+ id: self.selectKeyId,
+ items: $.map(key.label, function(value, valuePos) {
+ return {
+ checked: valuePos == self.selectedKey[keyPos],
+ id: value.id,
+ group: self.selectKeyId, // fixme: same id, works here, but should be different
+ title: value.title
+ };
+ }),
+ overlap: "right",
+ type: self.options.label ? "text" : "image",
+ width: self.options.label ? (self.options.label.length == 1 ? self.options.labelWidth : key.width) : self.placeholderWidth
+ })
+ .css({
+ float: "left"
+ })
+ .appendTo(that);
+ that.bindEvent("change_" + self.selectKeyId, changeKey);
+ }
+ });
+ }
+
+ if (self.options.clear) {
+ that.$clear = new Ox.Button({
+ overlap: "left",
+ type: "image",
+ value: "clear"
+ })
+ .css({
+ float: "right"
+ })
+ .click(clear)
+ .appendTo(that);
+ }
+
+ if (self.options.unit.length == 1) {
+ that.$unit = new Ox.Label({
+ overlap: "left",
+ title: self.options.unit[0].title,
+ width: self.options.unitWidth
+ })
+ .css({
+ float: "right"
+ })
+ .click(function() {
+ that.$input[0].focus();
+ })
+ .appendTo(that);
+ } else if (self.options.unit.length > 1) {
+ self.selectUnitId = self.options.id + "Unit";
+ that.$unit = new Ox.Select({
+ id: self.selectUnitId,
+ items: $.map(self.options.unit, function(unit, i) {
+ Ox.print("unit", unit)
+ return {
+ checked: i == 0,
+ id: unit.id,
+ group: self.selectUnitId, // fixme: same id, works here, but should be different
+ title: unit.title
+ };
+ }),
+ overlap: "left",
+ size: self.options.size,
+ width: self.options.unitWidth
+ })
+ .css({
+ float: "right"
+ })
+ .appendTo(that);
+ }
+
+ if (self.values) {
+ that.$separator = [];
+ $.each(self.options.value, function(i, v) {
+ if (i < self.values - 1) {
+ that.$separator[i] = new Ox.Label({
+ textAlign: "center",
+ title: self.options.separator[i],
+ width: self.options.separatorWidth[i] + 32
+ })
+ .css({
+ float: "left",
+ marginLeft: (v.width - (i == 0 ? 16 : 32)) + "px"
+ })
+ .click(function() {
+ that.$input[0].focus();
+ })
+ .appendTo(that);
+ }
+ });
+ }
+ that.$input = [];
+ //self.margin = 0;
+ $.each(self.options.value, function(i, v) {
+ Ox.print("o k i", self.options, self.keyName, i);
+ var id = self.keyName ? $.map(self.selectedKey, function(v, i) {
+ return self.options[self.keyName][i].id;
+ }).join(".") : "";
+ //self.margin -= (i == 0 ? 16 : self.options.value[i - 1].width)
+ Ox.print("v:", v, "id:", id)
+ if (self.options.type == "select") {
+ that.$input[i] = new Ox.Select({
+ id: v.id,
+ items: v.items,
+ width: v.width
+ }).
+ css({
+ float: "left"
+ });
+ } else if (self.options.type == "range") {
+ that.$input[i] = new Ox.Range(v)
+ .css({
+ float: "left"
+ });
+ } else {
+ that.$input[i] = new Ox.InputElement({
+ autocomplete: self.options.autocomplete[id],
+ autocorrect: self.options.autocorrect[id],
+ autosuggest: self.options.autosuggest[id],
+ autosuggestHighlight: self.options.autosuggestHighlight,
+ autosuggestSubmit: self.options.autosuggestSubmit,
+ autovalidate: self.options.autovalidate[id],
+ autovalidateName: self.options.autovalidateName,
+ disabled: self.options.disabled,
+ height: self.options.height,
+ id: self.options.id + "Input" + Ox.toTitleCase(v.id),
+ key: self.hasSelectableKeys ? self.options[self.keyName][0].label[self.selectedKey[0]].id : "",
+ parent: that,
+ placeholder: self.options.placeholder ? self.options.placeholder[0].label[0].title : "",
+ size: self.options.size,
+ type: self.options.type,
+ value: v.value,
+ width: v.width
+ });
+ }
+ that.$input[i]
+ .css($.extend({}, self.options.value.length > 1 ? {
+ float: "left",
+ marginLeft: -Ox.sum($.map(self.options.value, function(v_, i_) {
+ return i_ > i ? self.options.value[i_ - 1].width + self.options.separatorWidth[i_ - 1] : (i_ == i ? 16 : 0);
+ }))
+ } : {}))
+ .appendTo(that);
+ });
+
+ //width(self.options.width);
+
+ function changeKey(event, data) {
+ Ox.print("changeKey", data);
+ if (data) { // fixme: necessary?
+ self.key = {
+ id: data.id,
+ title: data.value // fixme: should be data.title
+ };
+ that.$input[0].options({
+ key: data.id
+ });
+ }
+ if (self.options.label) {
+ //that.$label.html(self.option.title);
+ that.$input[0].focus();
+ //autocompleteCall();
+ } else {
+ that.$input[0].options({
+ placeholder: data.value // fixme: should be data.title
+ });
+ /*
+ if (that.$input.hasClass("OxPlaceholder")) {
+ that.$input.val(self.key.title);
+ //that.$input.focus();
+ } else {
+ that.$input.focus();
+ self.options.autosuggest && autosuggestCall();
+ }
+ */
+ }
+ }
+
+ function changeUnit() {
+ that.$input[0].focus();
+ }
+
+ function clear() {
+ $.each(that.$input, function(i, v) {
+ v.val("");
+ });
+ that.$input[0].focus();
+ }
+
+ function height(value) {
var stop = 8 / value;
if (self.options.type == "textarea") {
that.$element
@@ -2418,65 +4887,370 @@ requires
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) {
+ function selectUnit() {
+ self.$selectUnitMenu.show();
+ }
+
+ function submit() {
+ Ox.print("submit")
+ var value = that.$input.val();
+ that.$input.blur();
+ that.triggerEvent("submit", self.options.key ? {
+ key: self.options.key,
+ value: value
+ } : value);
+ }
+
+ function width(value) {
that.$element.width(value);
- that.$input.width(value - (self.options.type == "textarea" ? 0 : 2) -
- (self.options.label ? self.options.labelWidth + 25 : 0) -
- (self.options.placeholder.length > 1 ? 16 : 0) -
- (self.options.clear ? 25 : 0));
- // fixme: the values above are all weird guesswork
- return that;
+ that.$input.width(
+ value - (self.options.type == "textarea" ? 0 : 12) -
+ (self.options.label ? self.options.labelWidth : 0) -
+ (self.options.placeholder.length > 1 ? 16 : 0) -
+ (self.options.unit ? self.options.unitWidth : 0) -
+ (self.options.clear ? 16 : 0)
+ );
+ }
+
+ self.onChange = function(key, value) {
+ if (key == "height") {
+ height(value);
+ } else if (key == "width") {
+ width(value);
+ }
+ };
+
+ that.changeLabel = function(id) {
+ that.$key.html(Ox.getObjectById(self.options.label, id).title);
+ self.selectMenu.checkItem(id);
+ };
+
+ return that;
+
+ }
+
+ Ox.InputElement_ = function(options, self) {
+
+ var self = self || {},
+ that = new Ox.Element(
+ options.type == "textarea" ? "textarea" : "input", self
+ )
+ .defaults({
+ autocomplete: null,
+ autocorrect: null,
+ autosuggest: null,
+ autosuggestHighlight: false,
+ autosuggestSubmit: false,
+ autovalidate: null,
+ disabled: false,
+ height: 128,
+ id: "",
+ key: "",
+ parent: null,
+ placeholder: "",
+ size: "medium",
+ type: "text",
+ value: "",
+ width: 128
+ })
+ .options(options || {})
+ .addClass("OxInput Ox" + Ox.toTitleCase(self.options.size) + (
+ (self.options.placeholder && self.options.value === "") ?
+ " OxPlaceholder" : ""
+ ))
+ .attr(self.options.type == "textarea" ? {} : {
+ type: self.options.type
+ })
+ .css({
+ float: "left",
+ width: (self.options.width - 14) + "px"
+ })
+ .val(
+ (self.options.placeholder && self.options.value === "") ?
+ self.options.placeholder : self.options.value
+ )
+ .blur(blur)
+ .change(change)
+ .focus(focus);
+
+ Ox.print("InputElement self.options", self.options)
+
+ self.bindKeyboard = self.options.autocomplete || self.options.autocorrect ||
+ self.options.autosuggest || self.options.autovalidate;
+
+ if (self.options.autosuggest) {
+ self.autosuggestId = self.options.id + "Menu"; // fixme: we do this in other places ... are we doing it the same way? var name?
+ self.$autosuggestMenu = new Ox.Menu({
+ element: that.$element,
+ id: self.autosuggestId,
+ offset: {
+ left: 4,
+ top: 0
+ },
+ size: self.options.size
+ });
+ that.bindEvent("click_" + self.autosuggestId, clickMenu);
+ }
+
+ that.bindEvent($.extend(self.options.type == "textarea" ? {} : {
+ key_enter: submit
+ }, {
+ key_escape: cancel
+ }));
+
+ function autocomplete(value) {
+ var value = value.toLowerCase(),
+ ret = "";
+ if (value !== "") {
+ $.each(self.options.autocomplete, function(i, v) {
+ if (v.toLowerCase().indexOf(value) == 0) {
+ ret = v;
+ return false;
+ }
+ });
+ }
+ return ret;
+ }
+
+ function autocompleteCall() {
+ var value = that.$element.val();
+ Ox.isFunction(self.options.autocomplete) ?
+ self.options.autocomplete(self.options.key ? {
+ key: self.options.key,
+ value: value
+ } : value, autocompleteCallback) :
+ autocompleteCallback(autocomplete(value));
+ }
+
+ function autocompleteCallback(value) {
+ var pos = cursor()[0];
+ if (value) {
+ that.$element.val(value);
+ cursor(pos, value.length);
+ }
+ }
+
+ function autocorrect(value) {
+ var length = value.length;
+ return $.map(value.toLowerCase().split(""), function(v, i) {
+ if (new RegExp(self.options.autocorrect)(v)) {
+ return v
+ } else {
+ return null;
+ }
+ }).join("");
+ }
+
+ function autocorrectCall(blur) {
+ var blur = blur || false,
+ value = that.$element.val(),
+ pos = cursor()[0];
+ Ox.isFunction(self.options.autocorrect) ?
+ self.options.autocorrect(value, blur, autocorrectCallback) :
+ autocorrectCallback(autocorrect(value), blue);
+ }
+
+ function autocorrectCallback(value, blur) {
+ var length = that.$element.val().length;
+ that.$element.val(self.options.value);
+ !blur && cursor(pos + value.length - length);
+ }
+
+ function autosuggest(value) {
+ var value = value.toLowerCase(),
+ values = [[], []];
+ if (value !== "") {
+ $.each(self.options.key ? self.options.autosuggest[self.options.key] : self.options.autosuggest, function(i, v) {
+ //Ox.print("v...", v)
+ var index = v.toLowerCase().indexOf(value);
+ index > -1 && values[index == 0 ? 0 : 1].push(v);
+ });
+ }
+ return $.merge(values[0], values[1]);
+ }
+
+ function autosuggestCall() {
+ var value = that.$element.val();
+ Ox.isFunction(self.options.autosuggest) ?
+ self.options.autosuggest(self.options.key ? {
+ key: self.options.key,
+ value: value
+ } : value, autosuggestCallback) :
+ autosuggestCallback(autosuggest(value));
+ }
+
+ function autosuggestCallback(values) {
+ var values = values || [],
+ selected = values.length == 1 ? 0 : -1,
+ value = that.$element.val().toLowerCase();
+ //Ox.print("values", values);
+ if (values.length) {
+ values = $.map(values, function(v, i) {
+ if (value == v.toLowerCase()) {
+ selected = i;
+ }
+ return {
+ id: v.toLowerCase().replace(/ /g, "_"), // fixme: need function to do lowercase, underscores etc?
+ title: self.options.autosuggestHighlight ? v.replace(
+ new RegExp("(" + value + ")", "ig"),
+ "
$1"
+ ) : v
+ };
+ });
+ // self.selectMenu && self.selectMenu.hideMenu(); // fixme: need event
+ self.$autosuggestMenu.options({
+ items: values,
+ selected: selected
+ }).showMenu();
+ } else {
+ self.$autosuggestMenu.hideMenu();
+ }
+ }
+
+ function autovalidate(value) {
+ return {
+ valid: self.options.autovalidate(value) != null,
+ message: "Invalid " + self.options.name
+ };
+ }
+
+ function autovalidateCall(blur) {
+ var blur = blur || false,
+ value = that.$element.val();
+ if (value !== "") {
+ Ox.isFunction(self.options.autovalidate) ?
+ self.options.autovalidate(value, autovalidateCallback) :
+ autovalidateCallback(autovalidate(value), blur);
+ } else {
+ autovalidateCallback({
+ blur: blur,
+ valid: false,
+ message: "Empty " + self.options.name
+ });
+ }
+ }
+
+ function autovalidateCallback(data, blur) {
+ if (data.valid != self.valid) {
+ self.valid = data.valid;
+ that.triggerEvent("validate", $.extend(data, {
+ blur: blur
+ }));
+ }
+ }
+
+ function blur() {
+ if (!self.options.autosuggest || self.$autosuggestMenu.is(":hidden")) {
+ Ox.print("losing focus...")
+ that.loseFocus();
+ self.options.parent.removeClass("OxFocus");
+ self.options.autocorrect && autocorrectCall(true);
+ // self.options.autosuggest && self.$autosuggestMenu.hideMenu();
+ self.options.autovalidate && autovalidateCall(true);
+ if (self.options.placeholder && that.$element.val() === "") {
+ that.$element.addClass("OxPlaceholder").val(self.options.placeholder);
+ }
+ }
+ if (self.bindKeyboard) {
+ $document.unbind("keydown", keypress);
+ $document.unbind("keypress", keypress);
+ }
+ }
+
+ function cancel() {
+ that.$element.blur();
+ }
+
+ function change() {
+
+ }
+
+ function clear() {
+ that.$element.val("").focus();
+ }
+
+ function clickMenu(event, data) {
+ Ox.print("clickMenu", data);
+ that.$element.val(data.title);
+ //self.$autosuggestMenu.hideMenu();
+ self.options.autosuggestSubmit && submit();
+ }
+
+ function cursor(start, end) {
+ /*
+ cursor() returns [start, end]
+ cursor(start) sets start
+ cursor([start, end]) sets start and end
+ cursor(start, end) sets start and end
+ */
+ var isArray = Ox.isArray(start);
+ if (arguments.length == 0) {
+ return [that.$element[0].selectionStart, that.$element[0].selectionEnd];
+ } else {
+ start = isArray ? start[0] : start;
+ end = isArray ? start[1] : (end ? end : start);
+ that.$element[0].setSelectionRange(start, end);
+ }
+ }
+
+ function focus() {
+ var val = that.$element.val();
+ that.gainFocus();
+ self.options.parent.addClass("OxFocus");
+ if (that.$element.hasClass("OxPlaceholder")) {
+ that.$element.val("").removeClass("OxPlaceholder");
+ }
+ if (self.bindKeyboard) {
+ // fixme: different in webkit and firefox (?), see keyboard handler, need generic function
+ $document.keydown(keypress);
+ $document.keypress(keypress);
+ Ox.print("calling autosuggest...")
+ self.options.autosuggest && setTimeout(autosuggestCall, 0); // fixme: why is the timeout needed?
+ }
+ }
+
+ function keypress(event) {
+ Ox.print("keyCode", event.keyCode)
+ if (event.keyCode != 9 && event.keyCode != 13 && event.keyCode != 27) { // fixme: can't 13 and 27 return false?
+ setTimeout(function() { // fixme: document what this timeout is for
+ var value = that.$element.val();
+ if (value != self.options.value) {
+ self.options.value = value;
+ self.options.autocomplete && autocompleteCall();
+ self.options.autocorrect && autocorrectCall();
+ self.options.autosuggest && autosuggestCall();
+ self.options.autovalidate && autovalidateCall();
+ }
+ }, 25);
+ }
+ }
+
+ function submit() {
+
+ }
+
+ self.onChange = function(key, value) {
+ if (key == "placeholder") {
+ that.$element.hasClass("OxPlaceholder") && that.$element.val(value);
+ } else if (key == "value") {
+ if (self.options.placeholder) {
+ if (value === "") {
+ that.$element.addClass("OxPlaceholder").val(self.options.placeholder);
+ } else {
+ that.$element.removeClass("OxPlaceholder");
+ }
+ }
+ change(); // fixme: keypress too
+ }
}
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) {
+ Ox.Range_ = function(options, self) {
/*
init
@@ -2497,14 +5271,18 @@ requires
thumbValue: false,
trackImages: [],
trackStep: 0,
- value: 0
+ value: 0,
+ valueNames: null
})
.options($.extend(options, {
arrowStep: options.arrowStep ?
options.arrowStep : options.step,
trackImages: $.makeArray(options.trackImages || [])
}))
- .addClass("OxRange");
+ .addClass("OxRange")
+ .css({
+ width: self.options.size + "px"
+ });
// fixme: self. ... ?
var trackImages = self.options.trackImages.length,
@@ -2532,32 +5310,35 @@ requires
var $track = new Ox.Element()
.addClass("OxTrack")
.mousedown(clickTrack)
- .appendTo(that.$element); // fixme: make that work
+ .appendTo(that.$element);
if (trackImages) {
var width = parseFloat(screen.width / trackImages),
- $image = $("
")
+ $image = $("