form elements rewrite, part 1

This commit is contained in:
rlx 2011-12-21 13:42:47 +00:00
parent cf567e5608
commit 7f83cd3141
30 changed files with 1061 additions and 958 deletions

View file

@ -8,6 +8,17 @@ Ox.load('UI', function() {
.css({margin: '16px'})
.appendTo(Ox.$body);
Ox.Button({
title: 'Value'
})
.css({marginLeft: '16px'})
.bindEvent({
click: function() {
Ox.print($arrayInput.options('value'));
}
})
.appendTo(Ox.$body)
Ox.Button({
title: 'Reset'
})

View file

@ -6,6 +6,9 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
id: "panel"
})
.appendTo($body),
countries = Ox.sortASCII(Ox.map(Ox.COUNTRIES, function(country) {
return country.dissolved ? null : country.name;
}));
objects = {
"Button": [
{
@ -60,7 +63,8 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
{id: "off", title: "Off"},
{id: "on", title: "On"},
],
width: 32
width: 32,
value: 'on'
},
title: "Multi-Title Selectable Text Button"
}
@ -69,65 +73,21 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
{
options: {
buttons: [
{ id: "", title: "add" },
{ id: "", title: "remove" },
{ id: "", title: "close" },
{ id: "", title: "select" },
{ id: "", title: "arrowLeft" },
{ id: "", title: "arrowRight" },
{ id: "", title: "arrowUp" },
{ id: "", title: "arrowDown" },
{ id: "", title: "left" },
{ id: "", title: "right" },
{ id: "", title: "up" },
{ id: "", title: "down" },
{ id: "", title: "pause" },
{ id: "", title: "playInToOut" },
{ id: "", title: "goToIn" },
{ id: "", title: "goToOut" },
{ id: "", title: "setIn" },
{ id: "", title: "setOut" },
{ id: "", title: "goToPoster" },
{ id: "", title: "setPoster" },
{ id: "", title: "center" },
{ id: "", title: "zoom" },
{ id: "", title: "grow" },
{ id: "", title: "shrink" },
{ id: "", title: "fill" },
{ id: "", title: "fit" },
{ id: "", title: "unmute" },
{ id: "", title: "volumeUp" },
{ id: "", title: "volumeDown" },
{ id: "", title: "mute" },
{ id: "", title: "undo" },
{ id: "", title: "redo" },
{ id: "", title: "unlock" },
{ id: "", title: "lock" },
{ id: "", title: "volume" },
{ id: "", title: "mount" },
{ id: "", title: "unmount" },
{ id: "", title: "sync" },
{ id: "", title: "info" },
{ id: "", title: "warning" },
{ id: "", title: "help" },
{ id: "", title: "check" },
{ id: "", title: "embed" },
{ id: "", title: "bracket" },
{ id: "", title: "upload" },
{ id: "", title: "download" },
{ id: "", title: "click" },
{ id: "", title: "delete" },
{ id: "", title: "edit" },
{ id: "", title: "find" },
{ id: "", title: "flag" },
{ id: "", title: "icon" },
{ id: "", title: "like" },
{ id: "", title: "publish" },
{ id: "", title: "set" },
{ id: "", title: "star" },
{ id: "", title: "user" },
{ id: "", title: "view" },
{ id: "", title: "loading" }
'Add', 'Remove', 'Close', 'Select',
'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown',
'Left', 'Right', 'Up', 'Down',
'Pause', 'PlayInToOut', 'GoToIn', 'GoToOut', 'SetIn', 'SetOut',
'GoToPoster', 'SetPoster',
'Center', 'Zoom', 'Grow', 'Shrink', 'Fill', 'Fit',
'Unmute', 'VolumeUp', 'VolumeDown', 'Mute',
'Undo', 'Redo', 'Unlock', 'Lock',
'Volume', 'Mount', 'Unmount', 'Sync',
'Info', 'Warning', 'Help',
'Check', 'Embed', 'Bracket',
'Upload', 'Download',
'Copyright', 'NoCopyright',
'Click', 'Delete', 'Edit', 'Find', 'Flag', 'Icon', 'Like',
'Mail', 'Publish', 'Set', 'Star', 'User', 'View', 'Loading'
],
id: "buttonGroupImage",
type: "image"
@ -236,7 +196,8 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
id: "selectableButtonGroupAny",
max: -1,
min: 0,
selectable: true
selectable: true,
value: 'and1'
},
title: "Selectable ButtonGroup, select any"
},
@ -265,8 +226,10 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
],
"Checkbox": [
{
options: {},
title: "Checkbox"
options: {
value: true
},
title: "Checkbox",
},
{
options: {
@ -326,6 +289,7 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
id: "CheckboxGroupAny",
max: -1,
min: 0,
value: 'and1',
width: 300
},
title: "CheckboxGroup, select any"
@ -400,6 +364,15 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
title: "Short DateTimeInput"
},
{
options: {
format: 'medium',
id: "dateTimeInputMedium",
seconds: true,
weekday: true
},
title: "Medium DateTimeInput"
},
{
options: {
ampm: true,
@ -486,8 +459,14 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
width: 208
})
],
join: function(value) {
return value[1][0];
},
float: "left",
id: "formElementGroupLabels"
id: "formElementGroupLabels",
split: function(value) {
return [null, [value, null]];
}
},
title: "FormElementGroup (Select and Labels)"
},
@ -495,30 +474,26 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
options: {
elements: [
new Ox.Select({
id: "selectOne",
items: [
{id: "one", title: "Title"},
{id: "two", title: "Date"},
{id: "three", title: "Place"}
{id: "title", title: "Title"},
{id: "date", title: "Date"},
{id: "place", title: "Place"}
],
overlap: "right",
width: 128
}),
new Ox.Select({
id: "selectTwo",
items: [
{id: "one", title: "is"},
{id: "two", title: "is between"},
{id: "three", title: "is not between"}
{id: "is", title: "is"},
{id: "is_between", title: "is between"},
{id: "is_not_between", title: "is not between"}
],
overlap: "right",
width: 128
}),
new Ox.InputGroup({
id: "input",
inputs: [
new Ox.DateInput({
id: "inputOne",
width: {
day: 36,
month: 36,
@ -526,7 +501,6 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
}
}),
new Ox.DateInput({
id: "inputTwo",
width: {
day: 36,
month: 36,
@ -539,9 +513,9 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
]
})
],
id: "formElementGroupSelectSelectInput"
id: "formElementGroupSelectInputGroup",
},
title: "FormElementGroup (two Selects, one Input)"
title: "FormElementGroup (Selects and InputGroup)"
}
],
"Input": [
@ -633,9 +607,7 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
{
options: {
autocomplete: Ox.sortASCII(Ox.COUNTRIES.map(function(v, i) {
return v.name;
})),
autocomplete: countries,
autocompleteReplace: true,
id: "autocompleteReplace"
},
@ -643,9 +615,7 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
{
options: {
autocomplete: Ox.sortASCII(Ox.COUNTRIES.map(function(v, i) {
return v.name;
})),
autocomplete: countries,
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: "autocompleteReplaceCorrect"
@ -654,9 +624,7 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
{
options: {
autocomplete: Ox.sortASCII(Ox.COUNTRIES.map(function(v, i) {
return v.name;
})),
autocomplete: countries,
autocompleteSelect: true,
autocompleteSelectHighlight: true,
id: "autocompleteSelect"
@ -665,9 +633,7 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
{
options: {
autocomplete: Ox.sortASCII(Ox.COUNTRIES.map(function(v, i) {
return v.name;
})),
autocomplete: countries,
autocompleteReplace: true,
autocompleteSelect: true,
autocompleteSelectHighlight: true,
@ -677,9 +643,7 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
{
options: {
autocomplete: $.map(Ox.COUNTRIES, function(v, i) {
return v.name;
}),
autocomplete: countries,
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
autocompleteSelect: true,
@ -761,6 +725,48 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
title: "InputGroup with Width"
},
{
options: {
id: "inputGroupWithSplitAndJoin",
inputs: [
Ox.Input({id: "width", placeholder: "Width"}),
Ox.Input({id: "height", placeholder: "Height"})
],
join: function(value) {
return value.join('x');
},
separators: [
{title: "x", width: 16}
],
split: function(value) {
return value.split('x');
},
value: '256x96',
width: 128
},
title: "InputGroup with Split and Join"
},
{
options: {
id: "inputGroupWithObjectValue",
inputs: [
Ox.Input({id: "width", placeholder: "Width"}),
Ox.Input({id: "height", placeholder: "Height"})
],
join: function(value) {
return {width: value[0], height: value[1]};
},
separators: [
{title: "x", width: 16}
],
split: function(value) {
return [value.width, value.height];
},
value: {width: 256, height: 96},
width: 128
},
title: "InputGroup with Object Value"
},
{
options: {
id: "inputGroupUsernamePassword",
@ -818,10 +824,10 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
new Ox.Select({
items: [
{id: "items", title: "items"},
{},
//{},
{id: "hours", title: "hours"},
{id: "days", title: "days"},
{},
//{},
{id: "GB", title: "GB"},
],
overlap: "left",
@ -919,32 +925,34 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
size: 48,
thumbSize: 32,
thumbValue: true,
valueNames: ["Off", "On"]
values: ["Off", "On"]
},
title: "Range with Value Names"
title: "Range with Values"
},
{
options: {
id: "rangeTrackColors",
max: 255,
min: 0,
size: 400,
thumbSize: 40,
size: 360,
thumbValue: true,
trackColors: [
"rgb(0, 0, 0)",
"rgb(255, 255, 255)"
"rgb(255, 0, 0)",
"rgb(255, 255, 0)",
"rgb(0, 255, 0)",
"rgb(0, 255, 255)",
"rgb(0, 0, 255)",
"rgb(255, 0, 255)"
],
values: ['Red', 'Yellow', 'Green', 'Cyan', 'Blue', 'Magenta']
},
title: "Range with Track Colors"
},
{
options: {
id: "rangeTrackColorsColor",
id: "rangeTrackGradientColor",
max: 359,
min: 0,
size: 400,
thumbSize: 40,
size: 360,
thumbSize: 36,
thumbValue: true,
trackColors: [
"rgb(255, 0, 0)",
@ -954,41 +962,41 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
"rgb(0, 0, 255)",
"rgb(255, 0, 255)",
"rgb(255, 0, 0)"
]
],
trackGradient: true
},
title: "Range with Track Colors"
title: "Range with Track Gradient"
},
{
options: {
id: "rangeTrackGradient",
max: 255,
min: 0,
size: 360,
thumbSize: 36,
thumbValue: true,
trackColors: [
"rgb(0, 0, 0)",
"rgb(255, 255, 255)"
],
trackGradient: true
},
title: "Range with Track Gradient"
},
{
options: {
id: "rangeTrackImage",
size: 400,
size: 360,
trackImages: ["png/timeline.png"]
},
title: "Range with Track Image"
},
{
options: {
id: "rangeTrackImages",
max: 5,
size: 386,
thumbValue: true,
trackImages: [
"png/red.png",
"png/yellow.png",
"png/green.png",
"png/cyan.png",
"png/blue.png",
"png/magenta.png"
],
valueNames: ["Red", "Yellow", "Green", "Cyan", "Blue", "Magenta"]
},
title: "Range with Track Images"
},
{
options: {
id: "rangeTrackImages",
max: 9,
size: 240,
thumbStyle: 'transparent',
trackImages: [
"jpg/Children's Games.jpg",
"jpg/Dulle Griet.jpg",
@ -1006,6 +1014,13 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
],
"Select": [
{
options: {
id: 'simpleSelect',
items: ['foo', 'bar', 'baz']
},
title: 'Simple Select'
},
{
options: {
id: "imageSelectOne",
@ -1071,19 +1086,6 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
},
title: "Text Select, select any"
},
{
options: {
id: "textSelectNone",
items: [
{id: "one", title: "Item One"},
{id: "two", title: "Item Two"},
{id: "three", title: "Item Three"}
],
selectable: false,
title: "Title..."
},
title: "Text Select, select none"
},
{
options: {
id: "textSelectWidth",
@ -1110,6 +1112,20 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
title: "Text Select with Max Width"
}
],
'SelectInput': [
{
options: {
id: 'selectInput',
items: [
{id: 'male', title: 'Male'},
{id: 'female', title: 'Female'},
{id: 'other', title: 'Other...'}
],
width: 256
},
title: 'SelectInput'
}
],
"TimeInput": [
{
options: {
@ -1167,7 +1183,7 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
// if (object != "PlaceInput") return;
$.each(elements, function(i, element) {
var $div = $("<div>").appendTo($panel),
$label, $element, $button;
$label, $element;
$label = Ox.Label({
textAlign: "right",
title: element.title,
@ -1182,11 +1198,42 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
} catch(error) {
}
Ox.Button({
title: 'Options'
})
.addClass("margin")
.bindEvent({
click: function() {
var $dialog = Ox.Dialog({
buttons: [
Ox.Button({
id: 'close',
title: 'Close'
}).bindEvent({
click: function() { $dialog.close(); }
})
],
content: $('<div>')
.css({margin: '16px'})
.html(
JSON.stringify(Ox.map($element.options(), function(val, key) {
return Ox.isEqual(val, $element.defaults(key)) ? null : val;
}), void 0, 4)
.replace(/\n/g, '<br/>')
.replace(/\s/g, '&nbsp;')
),
height: 256,
title: "Options",
width: 384
}).open()
}
})
.appendTo($div);
$element = Ox[object](element.options)
.addClass("margin")
.appendTo($div);
if (object != "Button" && object != "Label") {
$button = Ox.Button({
Ox.Button({
id: "id" + Ox.uid(),
title: "Value"
})
@ -1202,11 +1249,18 @@ Ox.load({UI: {}, Geo:{}, Unicode: {}}, function() {
click: function() { $dialog.close(); }
})
],
content: $('<div>').css({margin: '16px'}).html(Ox.isUndefined(value) ? "undefined" : value),
height: 128,
id: "value",
content: $('<div>')
.css({margin: '16px'})
.html(
Ox.isUndefined(value)
? "undefined"
: JSON.stringify(value, void 0, 4)
.replace(/\n/g, '<br/>')
.replace(/\s/g, '&nbsp;')
),
height: 256,
title: "Value",
width: 256
width: 384
})
.open();
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -930,12 +930,12 @@ OxRange
.OxRange > .OxTrack > .OxThumb {
float: left;
margin: -1px;
//margin-left: -1px;
//margin-top: -1px;
text-align: center;
}
.OxRange > .OxTrack > .OxThumb:first-child {
//margin-top: -1px;
.OxRange > .OxTrack > .OxThumb.OxTransparent {
border: 1px solid white;
background: transparent;
box-shadow: 0 0 1px white inset;
}
/*
--------------------------------------------------------------------------------

View file

@ -328,16 +328,23 @@ Ox.Element = function(options, self) {
};
/*@
defaults <function> Sets the default options for an element object
defaults <function> Gets or sets the default options for an element object
({key: value, ...}) -> <obj> This element object
key <str> The name of the default option
value <val> The value of the default option
@*/
that.defaults = function(defaults) {
// sets the default options
self.defaults = defaults;
self.options = defaults;
return that;
that.defaults = function() {
var ret;
if (arguments.length == 0) {
ret = self.defaults;
} else if (Ox.isString(arguments[0])) {
ret = self.defaults[arguments[0]];
} else {
self.defaults = arguments[0];
self.options = Ox.clone(self.defaults);
ret = that;
}
return ret;
};
/*@
@ -386,14 +393,6 @@ Ox.Element = function(options, self) {
return Ox.getset(self.options, arguments, self.setOption, that);
};
that.setElement = function($element) {
//$element[0].className = that.$element[0].className;
$element.addClass('OxElement').data({oxid: that.id});
that.$element.replaceWith($element);
that.$element = $element;
that[0] = that.$element[0];
};
/*@
removeElement <function> Removes an element object and its event handler
() -> <obj> This element
@ -413,6 +412,22 @@ Ox.Element = function(options, self) {
return that;
};
that.setElement = function($element) {
//$element[0].className = that.$element[0].className;
$element.addClass('OxElement').data({oxid: that.id});
that.$element.replaceWith($element);
that.$element = $element;
that[0] = that.$element[0];
};
that.toggleOption = function() {
var options = {};
Ox.toArray(arguments[0]).forEach(function(key) {
options[key] == !self.options[key];
});
that.options(options);
};
/*@
triggerEvent <function> Triggers an event
(event) -> <object> This element object

View file

@ -59,7 +59,7 @@ Ox.ArrayInput = function(options, self) {
.bindEvent({
change: function(data) {
self.options.sort && data.value !== '' && sortInputs();
self.options.value = that.value();
self.options.value = getValue();
that.triggerEvent('change', {
value: self.options.value
});
@ -77,7 +77,7 @@ Ox.ArrayInput = function(options, self) {
var index = $(this).parent().data('index');
if (self.$input[index].value() !== '') {
self.$input[index].options({value: ''});
self.options.value = that.value();
self.options.value = getValue();
that.triggerEvent('change', {
value: self.options.value
});
@ -106,6 +106,13 @@ Ox.ArrayInput = function(options, self) {
updateInputs();
}
function getValue() {
return Ox.map(self.$input, function($input) {
var value = $input.value();
return value === '' ? null : value;
});
};
function removeInput(index) {
Ox.Log('Form', 'remove', index);
[
@ -118,6 +125,18 @@ Ox.ArrayInput = function(options, self) {
updateInputs();
}
function setValue() {
if (self.options.value.length == 0) {
self.options.value = [''];
}
while (self.$input.length) {
removeInput(0);
}
self.options.value.forEach(function(value, i) {
addInput(i, value);
});
}
function setWidths() {
self.$label && self.$label.options({width: self.options.width})
self.$element.forEach(function($element, i) {
@ -151,15 +170,7 @@ Ox.ArrayInput = function(options, self) {
self.setOption = function(key, value) {
if (key == 'value') {
if (self.options.value.length == 0) {
self.options.value = [''];
}
while (self.$input.length) {
removeInput(0);
}
self.options.value.forEach(function(value, i) {
addInput(i, value);
});
setValue();
} else if (key == 'width') {
setWidths();
}
@ -171,16 +182,6 @@ Ox.ArrayInput = function(options, self) {
});
};
// fixme: can't we generally use options.value for this?
that.value = function() {
if (arguments.length == 0) {
return Ox.map(self.$input, function($input) {
var value = $input.value();
return value === '' ? null : value;
});
}
};
return that;
};

View file

@ -1,5 +1,7 @@
// vim: et:ts=4:sw=4:sts=4:ft=javascript
'use strict';
/*@
Ox.Button <f:Ox.Element> Button Object
() -> <f> Button Object
@ -11,17 +13,16 @@ Ox.Button <f:Ox.Element> Button Object
id: <s|''> button id
overlap <s|none> overlap
selectable <b|false> is selecatable
selected <b|false> is selected
size <s|medium> button size
style <s|default> // can be default, checkbox, symbol, or tab
title <s|a|''> title, can be array of titles
tooltip <s|a|''> tooltip if multiple must be same number as titles
title <s|a|''> title, can be array
tooltip <s|a|''> tooltip, can be array (per title)
type <s|text> button type, text or image, (for image, title must be symbolTitle.svg must be availabe)
value <b|false> is selected
width <s|auto> button width
self <o> Shared private variable
click <!> non-selectable button was clicked
deselect <!> selectable button was deselected
select <!> selectable button was selected
change <!> selectable button was clicked
@*/
Ox.Button = function(options, self) {
@ -34,13 +35,13 @@ Ox.Button = function(options, self) {
id: '',
overlap: 'none',
selectable: false,
selected: false,
size: 'medium',
// fixme: 'default' or ''?
style: 'default',
title: '',
tooltip: '',
type: 'text',
value: false,
width: 'auto'
})
.options(options ? Ox.extend(Ox.clone(options), {
@ -51,29 +52,30 @@ Ox.Button = function(options, self) {
disabled: self.options.disabled,
type: self.options.type == 'text' ? 'button' : 'image'
})
.addClass('OxButton Ox' + Ox.toTitleCase(self.options.size) +
(self.options.disabled ? ' OxDisabled': '') +
(self.options.selected ? ' OxSelected': '') +
(self.options.style != 'default' ? ' Ox' + Ox.toTitleCase(self.options.style) : '') +
(self.options.overlap != 'none' ? ' OxOverlap' + Ox.toTitleCase(self.options.overlap) : ''))
.addClass(
'OxButton Ox' + Ox.toTitleCase(self.options.size)
+ (self.options.disabled ? ' OxDisabled': '')
+ (self.options.selectable && self.options.value ? ' 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.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
}]
});
if (Ox.isArray(self.options.title)) {
self.options.title = self.options.title.map(function(title) {
return {
id: title.id || title,
title: title.title || title
};
});
self.options.value = self.options.value || self.options.title[0].id;
}
setTitle(self.titles[self.selectedTitle].title);
setTitle();
if (options.tooltip) {
self.tooltips = Ox.toArray(options.tooltip);
@ -82,21 +84,14 @@ Ox.Button = function(options, self) {
function click() {
if (!self.options.disabled) {
var data = self.titles[self.selectedTitle];
if (!self.options.selectable) {
that.triggerEvent('click', data);
} else {
//self.options.selected = !self.options.selected;
//that.toggleClass('OxSelected');
if (self.options.group) {
that.triggerEvent('select', data);
} else {
that.toggleSelected();
//that.triggerEvent('change', {selected: self.options.selected});
}
}
if (self.titles.length == 2) {
if (Ox.isArray(self.options.title)) {
that.toggleTitle();
that.triggerEvent('change', {value: self.options.value});
} else if (self.options.selectable) {
that.toggleSelected();
that.triggerEvent('change', {value: self.options.value});
} else {
that.triggerEvent('click');
}
}
}
@ -108,8 +103,10 @@ Ox.Button = function(options, self) {
}
}
function setTitle(title) {
self.title = title;
function setTitle() {
var title = Ox.isArray(self.options.title)
? Ox.getObjectById(self.options.title, self.options.value).title
: self.options.title;
if (self.options.type == 'image') {
that.attr({
src: Ox.UI.getImageURL(
@ -125,15 +122,12 @@ Ox.Button = function(options, self) {
if (key == 'disabled') {
that.attr({disabled: value})
.toggleClass('OxDisabled');
} else if (key == 'selected') {
if (value != that.hasClass('OxSelected')) { // fixme: neccessary?
that.toggleClass('OxSelected');
}
that.triggerEvent('change');
} else if (key == 'tooltip') {
that.$tooltip.options({title: value});
} else if (key == 'title') {
setTitle(value);
setTitle();
} else if (key == 'value') {
self.options.selectable && that.toggleClass('OxSelected');
} else if (key == 'width') {
that.$element.css({
width: (value - 14) + 'px'
@ -141,37 +135,21 @@ Ox.Button = function(options, self) {
}
};
/*@
toggleDisabled <f>
() -> <u> toggle disabled state
@*/
that.toggleDisabled = function() {
that.options({
disabled: !self.options.disabled
});
return that;
//self.options.disabled = !self.options.disabled;
}
/*@
toggleSelected <f>
() -> <u> toggle selected state
@*/
that.toggleSelected = function() {
that.options({
selected: !self.options.selected
});
return that;
//self.options.selected = !self.options.selected;
}
self.options.value = !self.options.value;
that.toggleClass('OxSelected');
};
/*@
toggleTitle <f>
() -> <u> toggle through titles
() -> <o> toggle through titles
@*/
that.toggleTitle = function() {
self.selectedTitle = 1 - self.selectedTitle;
setTitle(self.titles[self.selectedTitle].title);
self.options.value = self.options.title[
1 - Ox.getPositionById(self.options.title, self.options.value)
].id;
setTitle();
self.options.selectable && that.toggleClass('OxSelected');
// fixme: if the tooltip is visible
// we also need to call show()
that.$tooltip && that.$tooltip.options({

View file

@ -27,10 +27,20 @@ Ox.ButtonGroup = function(options, self) {
size: 'medium',
style: '',
type: 'text',
value: options.max != 1 ? [] : ''
})
.options(options || {})
.addClass('OxButtonGroup');
self.options.buttons = self.options.buttons.map(function(button) {
return Ox.extend({
id: button.id || button,
title: button.title || button
}, self.options.selectable ? {
selected: Ox.toArray(self.options.value).indexOf(button.id || button) > -1
} : {});
});
if (self.options.selectable) {
self.optionGroup = new Ox.OptionGroup(
self.options.buttons,
@ -39,58 +49,51 @@ Ox.ButtonGroup = function(options, self) {
'selected'
);
self.options.buttons = self.optionGroup.init();
self.options.value = self.optionGroup.value();
}
self.$buttons = [];
self.options.buttons.forEach(function(button, position) {
self.options.buttons.forEach(function(button, pos) {
var id = self.options.id + Ox.toTitleCase(button.id)
self.$buttons[position] = Ox.Button({
self.$buttons[pos] = 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,
tooltip: button.tooltip,
type: self.options.type
type: self.options.type,
value: button.selected
})
.bindEvent('select', function() {
selectButton(position);
.bindEvent('change', function() {
self.options.selectable && toggleButton(pos);
})
.appendTo(that);
});
function selectButton(pos) {
function toggleButton(pos) {
var toggled = self.optionGroup.toggle(pos);
if (toggled.length) {
toggled.forEach(function(pos) {
self.$buttons[pos].toggleSelected();
Ox.print('TOGGLED::', toggled)
if (!toggled.length) {
self.$buttons[pos].options({
value: !self.$buttons[pos].options('value')
});
} else {
toggled.forEach(function(i) {
i != pos && self.$buttons[i].options({
// FIXME: fix and use that.toggleOption()
value: !self.$buttons[i].options('value')
});
});
self.options.value = self.optionGroup.value();
that.triggerEvent('change', {
selected: self.optionGroup.selected().map(function(i) {
return self.options.buttons[i].id;
})
value: self.options.value
});
}
}
that.select = function(id) {
// fixme: this doesn't work in cases where
// multiple buttons can be selected
var position = Ox.getPositionById(self.options.buttons, id);
if (position > -1) {
self.$buttons[position].trigger('click');
}
};
that.value = function() {
return self.optionGroup.selected().map(function(i) {
return self.options.buttons[i].id;
});
};
return that;
};

View file

@ -6,16 +6,16 @@ Ox.Checkbox <f:Ox.Element> Checkbox Element
(options) -> <f> Checkbox Element
(options, self) -> <f> Checkbox Element
options <o> Options object
checked <b> if true, checkbox is checked
disabled <b> if true, checkbox is disabled
group <b> if true, checkbox is part of a group
id <s> element id
label <s> Label (on the left side)
labelWidth <n|64> Label width
title <s> Title (on the right side)
value <b> if true, checkbox is checked
width <n> width in px
self <o> Shared private variable
change <!> triggered when checked property changes, passes {checked, id, title}
change <!> triggered when value changes
@*/
Ox.Checkbox = function(options, self) {
@ -23,7 +23,6 @@ Ox.Checkbox = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
checked: false,
disabled: false,
group: false,
id: '',
@ -31,6 +30,7 @@ Ox.Checkbox = function(options, self) {
labelWidth: 64,
overlap: 'none',
title: '',
value: false,
width: 'auto'
})
.options(options || {})
@ -72,27 +72,20 @@ Ox.Checkbox = function(options, self) {
self.$button = 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'
title: ['none', 'check'],
type: 'image',
value: self.options.value ? 'check' : 'none'
})
.addClass('OxCheckbox')
.bindEvent({
click: clickButton
change: clickButton
})
.appendTo(that);
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();
self.options.value = !self.options.value;
that.triggerEvent('change', {
checked: self.options.checked,
id: self.options.id,
title: self.options.title
value: self.options.value
});
}
@ -106,37 +99,20 @@ Ox.Checkbox = function(options, self) {
}
self.setOption = function(key, value) {
if (key == 'checked') {
that.toggleChecked();
} else if (key == 'disabled') {
if (key == 'disabled') {
that.attr({disabled: value});
self.$button.options({disabled: value});
self.$title && self.$title.options({disabled: value});
} else if (key == 'title') {
self.$title.options({title: value});
} else if (key == 'value') {
self.$button.toggleTitle();
} else if (key == 'width') {
that.css({width: value + 'px'});
self.$title && self.$title.options({width: getTitleWidth()});
}
};
/*@
checked <f> get current checked state
() -> <b> returns self.options.checked
@*/
that.checked = function() {
return self.options.checked;
}
/*@
toggleChecked <f> toggle current checked state
() -> <f> toggle state, returns Checkbox Element
@*/
that.toggleChecked = function() {
self.$button.toggleTitle();
return that;
}
// fixme: added for forms, duplicated, checked() shouldn't be neccessary
that.value = function() {
return self.options.checked;

View file

@ -1,5 +1,7 @@
// vim: et:ts=4:sw=4:sts=4:ft=javascript
'use strict';
/*@
Ox.CheckboxGroup <f:Ox.Element> CheckboxGroup Object
() -> <f> CheckboxGroup Object
@ -13,7 +15,7 @@ Ox.CheckboxGroup <f:Ox.Element> CheckboxGroup Object
width <n> width in px
self <o> shared private variable
change <!> triggered when checked property changes
passes {checked, id, title}
passes {id, title, value}
@*/
Ox.CheckboxGroup = function(options, self) {
@ -26,15 +28,25 @@ Ox.CheckboxGroup = function(options, self) {
max: 1,
min: 1,
type: 'group',
value: options.max != 1 ? [] : '',
width: 256
})
.options(options || {})
.addClass('OxCheckboxGroup Ox' + Ox.toTitleCase(self.options.type));
self.options.checkboxes = self.options.checkboxes.map(function(checkbox) {
return {
checked: Ox.toArray(self.options.value).indexOf(checkbox.id || checkbox) > -1,
id: checkbox.id || checkbox,
title: checkbox.title || checkbox
};
});
self.optionGroup = new Ox.OptionGroup(
self.options.checkboxes,
self.options.min,
self.options.max
self.options.max,
'checked'
);
self.options.checkboxes = self.optionGroup.init();
@ -48,37 +60,44 @@ Ox.CheckboxGroup = function(options, self) {
});
};
self.options.checkboxes.forEach(function(checkbox, index) {
self.$checkboxes[index] = Ox.Checkbox(Ox.extend(checkbox, {
self.options.checkboxes.forEach(function(checkbox, pos) {
self.$checkboxes[pos] = Ox.Checkbox(Ox.extend(checkbox, {
group: true,
id: checkbox.id,
width: self.options.type == 'group'
? self.checkboxWidth[index] : self.options.width
? self.checkboxWidth[pos] : self.options.width,
value: checkbox.checked
}))
.bindEvent('change', function() {
change(index);
toggleCheckbox(pos);
})
.appendTo(that);
});
function change(index) {
var toggled = self.optionGroup.toggle(index);
//Ox.Log('Form', 'change', index, 'toggled', toggled)
if (toggled.length) {
toggled.forEach(function(index, i) {
self.$checkboxes[index].toggleChecked();
function toggleCheckbox(pos) {
var toggled = self.optionGroup.toggle(pos);
Ox.Log('Form', 'change', pos, 'toggled', toggled)
if (!toggled.length) {
self.$checkboxes[pos].options({
value: !self.$checkboxes[pos].options('value')
});
} else {
toggled.forEach(function(i) {
i != pos && self.$checkboxes[i].options({
// FIXME: fix and use that.toggleOption()
value: !self.$checkboxes[i].options('value')
});
});
self.options.value = self.optionGroup.value();
that.triggerEvent('change', {
checked: self.optionGroup.checked().map(function(v) {
return self.options.checkboxes[v].id;
})
value: self.options.value
});
}
}
that.value = function() {
return self.options.checkboxes.filter(function(checkbox) {
return checkbox.checked;
return checkbox.value;
}).map(function(checkbox) {
return checkbox.id;
});

View file

@ -37,7 +37,7 @@ Ox.ColorInput = function(options, self) {
width: 40
})
.css({
background: 'rgb(' + getRGB() + ')'
background: 'rgb(' + getRGB().join(', ') + ')'
});
self.$inputs[4] = Ox.ColorPicker({
id: 'picker',
@ -52,6 +52,9 @@ Ox.ColorInput = function(options, self) {
value: self.options.value[i]
});
});
self.$inputs[3].css({
background: 'rgb(' + getRGB().join(', ') + ')'
});
}
})
.options({
@ -67,16 +70,16 @@ Ox.ColorInput = function(options, self) {
{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 <-- but we're passing self!
value: self.options.value
})
.bindEvent('change', change);
function change() {
self.options.value = self.$inputs.map(function(v) {
return v.options('value');
self.options.value = self.$inputs.map(function(input, i) {
return i < 3 ? input.options('value') : null;
});
self.$inputs[3].css({
background: 'rgb(' + getRGB() + ')'
background: 'rgb(' + getRGB().join(', ') + ')'
});
}

View file

@ -29,6 +29,7 @@ Ox.ColorPicker = function(options, self) {
Ox.loop(3, function(i) {
self.$ranges[i] = Ox.Range({
arrows: true,
changeOnDrag: true,
id: self.options.id + i,
max: self.options.mode == 'RGB' ? 255 : i == 0 ? 359 : 1,
size: self.options.mode == 'RGB' ? 328 : 432, // 256|360 + 16 + 40 + 16
@ -36,6 +37,7 @@ Ox.ColorPicker = function(options, self) {
thumbSize: 40,
thumbValue: true,
trackColors: getColors(i),
trackGradient: true,
value: self.options.value[i]
})
.css({

View file

@ -21,31 +21,28 @@ Ox.DateInput = function(options, self) {
var that;
self = Ox.extend(self || {}, {
options: Ox.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)
options: Ox.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 || {})
});
Ox.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 : Ox.SHORT_MONTHS,
weekdays: self.options.format == 'long' ? Ox.WEEKDAYS : Ox.SHORT_WEEKDAYS
});
self.formats = {
day: '%d',
month: self.options.format == 'short' ? '%m' :
(self.options.format == 'medium' ? '%b' : '%B'),
weekday: self.options.format == 'long' ? '%A' : '%a',
year: '%Y'
};
self.months = self.options.format == 'long' ? Ox.MONTHS : Ox.SHORT_MONTHS;
self.weekdays = self.options.format == 'long' ? Ox.WEEKDAYS : Ox.SHORT_WEEKDAYS;
self.$input = Ox.extend(self.options.weekday ? {
weekday: Ox.Input({
@ -53,7 +50,6 @@ Ox.DateInput = function(options, self) {
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'weekday',
value: Ox.formatDate(self.date, self.formats.weekday),
width: self.options.width.weekday
})
.bindEvent('autocomplete', changeWeekday),
@ -68,7 +64,6 @@ Ox.DateInput = function(options, self) {
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'day',
value: Ox.formatDate(self.date, self.formats.day),
textAlign: 'right',
width: self.options.width.day
})
@ -80,7 +75,6 @@ Ox.DateInput = function(options, self) {
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
})
@ -92,7 +86,6 @@ Ox.DateInput = function(options, self) {
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'year',
value: Ox.formatDate(self.date, self.formats.year),
textAlign: 'right',
width: self.options.width.year
})
@ -108,10 +101,7 @@ Ox.DateInput = function(options, self) {
] : [
self.$input.month, self.$input.day, self.$input.year
]),
joinValues: function(values) {
setValue();
return self.options.value;
},
join: join,
separators: Ox.merge(self.options.weekday ? [
{title: self.options.format == 'short' ? '' : ',', width: 8},
] : [], self.options.format == 'short' ? [
@ -119,11 +109,11 @@ Ox.DateInput = function(options, self) {
] : [
{title: '', width: 8}, {title: ',', width: 8}
]),
split: split,
value: self.options.value,
width: 0
}), self);
//Ox.Log('Form', 'SELF', self)
function changeDay() {
self.options.weekday && self.$input.weekday.options({
value: Ox.formatDate(new Date([
@ -132,7 +122,7 @@ Ox.DateInput = function(options, self) {
self.$input.year.options('value')
].join(' ')), self.formats.weekday)
});
setValue();
self.options.value = join();
}
function changeMonthOrYear() {
@ -151,16 +141,16 @@ Ox.DateInput = function(options, self) {
}),
value: self.options.format == 'short' ? Ox.pad(day, 2) : day.toString()
});
setValue();
self.options.value = join();
}
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.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: Ox.range(1, Ox.getDaysInMonth(date.year, date.month) + 1).map(function(i) {
@ -169,7 +159,12 @@ Ox.DateInput = function(options, self) {
value: date.day
});
self.$input.year.options({value: date.year});
setValue();
self.options.value = join();
Ox.print('self.options.value =', self.options.value)
}
function getDate(value) {
return new Date(self.options.value.replace(/-/g, '/'));
}
function getDateInWeek(weekday, month, day, year) {
@ -183,8 +178,18 @@ Ox.DateInput = function(options, self) {
};
}
function setValue() {
self.options.value = Ox.formatDate(new Date(self.options.format == 'short' ? [
function getValues() {
var date = getDate();
return {
day: Ox.formatDate(date, self.formats.day),
month: Ox.formatDate(date, self.formats.month),
weekday: Ox.formatDate(date, self.formats.weekday),
year: Ox.formatDate(date, self.formats.year)
};
}
function join() {
return Ox.formatDate(new Date(self.options.format == 'short' ? [
self.$input.year.options('value'),
self.$input.month.options('value'),
self.$input.day.options('value')
@ -195,28 +200,16 @@ Ox.DateInput = function(options, self) {
].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)
}
function split() {
var values = getValues();
return Ox.merge(self.options.weekday ? [
values.weekday
] : [], self.options.format == 'short' ? [
values.year, values.month, values.day
] : [
values.month, values.day, values.year
])
}
*/
/*
that.serialize = function() {
var normal = normalize();
return [normal.year, normal.month, normal.day].join('-');
}
*/
return that;

View file

@ -17,47 +17,55 @@ Ox.DateTimeInput <f:Ox.Element> DateTimeInput Element
Ox.DateTimeInput = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
ampm: false,
format: 'short',
seconds: false,
value: Ox.formatDate(new Date(), '%F %T'),
weekday: false
})
.options(options || {});
var that;
self = Ox.extend(self || {}, {
options: Ox.extend({
ampm: false,
format: 'short',
milliseconds: false,
seconds: false,
value: (function() {
var date = new Date();
return Ox.formatDate(
date,
'%F ' + (options.seconds || options.milliseconds ? '%T' : '%H:%M')
) + (options.milliseconds ? '.' + Ox.pad(date % 1000, 3) : '');
}()),
weekday: false
}, options || {})
});
self.values = self.options.value.split(' ');
//Ox.Log('Form', self.values)
self.options.seconds = self.options.seconds || self.options.milliseconds;
that = Ox.InputGroup({
inputs: [
Ox.DateInput({
format: self.options.format,
id: 'date',
value: self.values[0],
weekday: self.options.weekday
}),
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);
inputs: [
Ox.DateInput({
format: self.options.format,
id: 'date',
weekday: self.options.weekday
}),
Ox.TimeInput({
ampm: self.options.ampm,
id: 'time',
seconds: self.options.seconds
})
],
join: join,
separators: [
{title: '', width: 8}
],
split: split,
value: self.options.value
}, self);
function setValue() {
self.options.value = [
self.options('inputs')[0].options('value'),
self.options('inputs')[1].options('value')
].join(' ');
function join() {
return that.options('inputs').map(function($input) {
return $input.options('value');
}).join(' ');
}
function split() {
return self.options.value.split(' ');
}
return that;

View file

@ -24,17 +24,25 @@ Ox.FormElementGroup = function(options, self) {
id: '',
elements: [],
float: 'left',
joinValues: null,
join: null,
separators: [],
split: null,
value: options.split ? '' : [],
width: 0
})
.options(options || {})
.addClass('OxInputGroup');
if (Ox.isEmpty(self.options.value)) {
self.options.value = getValue();
} else {
setValue();
}
(
self.options.float == 'left' ?
self.options.elements : Ox.clone(self.options.elements).reverse()
).forEach(function($element, i) {
).forEach(function($element) {
$element.css({
float: self.options.float // fixme: make this a class
})
@ -42,12 +50,8 @@ Ox.FormElementGroup = function(options, self) {
autovalidate: function(data) {
that.triggerEvent({autovalidate: data});
},
change: function(data) {
that.triggerEvent({change: {value: that.value()}});
},
submit: function(data) {
that.triggerEvent({change: {value: that.value()}});
},
change: change,
submit: change,
validate: function(data) {
that.triggerEvent({validate: data});
}
@ -55,6 +59,13 @@ Ox.FormElementGroup = function(options, self) {
.appendTo(that);
});
function change(data) {
self.options.value = getValue();
that.triggerEvent('change', {
value: self.options.value
});
}
/*
if (self.options.width) {
setWidths();
@ -66,16 +77,34 @@ Ox.FormElementGroup = function(options, self) {
});
*/
function getValue() {
var value = self.options.elements.map(function($element) {
return $element.options('value');
});
return self.options.join ? self.options.join(value) : value;
}
function getWidth() {
}
function setValue() {
var values = self.options.split
? self.options.split(self.options.value)
: self.options.value;
values.forEach(function(value, i) {
self.options.elements[i].options({value: value});
});
}
function setWidth() {
}
self.setOption = function(key, value) {
if (key == 'value') {
setValue();
}
};
that.replaceElement = function(pos, element) {

View file

@ -593,9 +593,10 @@ Ox.Input = function(options, self) {
self.options.autovalidate && autovalidate(true);
self.options.placeholder && setPlaceholder();
self.options.validate && validate();
if (self.bindKeyboard) {
Ox.UI.$document.unbind('keydown', keydown);
}
self.bindKeyboard && Ox.UI.$document.unbind('keydown', keydown);
self.options.value !== self.originalValue && that.triggerEvent('change', {
value: self.options.value
});
// fixme: for some reason, if options.type is set, no change event fires
// as a workaround, blur sends a value. remove later...
!self.cancelled && !self.submitted && that.triggerEvent('blur', {
@ -768,7 +769,7 @@ Ox.Input = function(options, self) {
if (self.options.value === '') {
if (self.options.type == 'password') {
self.$placeholder.hide();
self.$input.show().focusInput(true);
self.$input.show().focus();
} else {
self.$input
.removeClass('OxPlaceholder')

View file

@ -18,16 +18,24 @@ Ox.InputGroup <f:Ox.Element> InputGroup Object
Ox.InputGroup = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
id: '',
inputs: [],
joinValues: null,
separators: [],
width: 0
})
.options(options || {})
.addClass('OxInputGroup')
.click(click);
.defaults({
id: '',
inputs: [],
join: null,
separators: [],
split: null,
value: options.split ? '' : [],
width: 0
})
.options(options || {})
.addClass('OxInputGroup')
.click(click);
if (Ox.isEmpty(self.options.value)) {
self.options.value = getValue();
} else {
setValue();
}
if (self.options.width) {
setWidths();
@ -41,7 +49,6 @@ Ox.InputGroup = function(options, self) {
self.$separator = [];
self.options.separators.forEach(function(v, i) {
self.options.id == 'debug' && Ox.Log('Form', 'separator #' + i + ' ' + self.options.inputs[i].options('id') + ' ' + self.options.inputs[i].options('width'))
self.$separator[i] = Ox.Label({
textAlign: 'center',
title: v.title,
@ -56,11 +63,10 @@ Ox.InputGroup = function(options, self) {
self.options.inputs.forEach(function($input, i) {
$input.options({
id: self.options.id + Ox.toTitleCase($input.options('id')),
parent: that
id: self.options.id + Ox.toTitleCase($input.options('id') || '')
})
.css({
marginLeft: -Ox.sum(self.options.inputs.map(function(v_, i_) {
marginLeft: -Ox.sum(self.options.inputs.map(function($input, i_) {
return i_ > i ? self.options.inputs[i_ - 1].options('width') +
self.options.separators[i_ - 1].width : (i_ == i ? 16 : 0);
})) + 'px'
@ -75,13 +81,9 @@ Ox.InputGroup = function(options, self) {
function change(data) {
//Ox.Log('Form', 'InputGroup change')
var values = self.options.inputs.map(function($input) {
return $input.value();
});
self.options.value = getValue();
that.triggerEvent('change', {
value: self.options.joinValues
? self.options.joinValues(values)
: values
value: self.options.value
});
}
@ -96,6 +98,13 @@ Ox.InputGroup = function(options, self) {
}
}
function getValue() {
var value = self.options.inputs.map(function($input) {
return $input.options('value');
});
return self.options.join ? self.options.join(value) : value;
}
function getWidth() {
return Ox.sum(self.options.inputs.map(function(v) {
return v.options('width');
@ -104,6 +113,15 @@ Ox.InputGroup = function(options, self) {
}));// + 2; // fixme: why + 2?
}
function setValue() {
var values = self.options.split
? self.options.split(self.options.value)
: self.options.value;
values.forEach(function(value, i) {
self.options.inputs[i].options({value: value});
});
}
function setWidths() {
var length = self.options.inputs.length,
inputWidths = Ox.divideInt(
@ -123,6 +141,12 @@ Ox.InputGroup = function(options, self) {
that.triggerEvent('validate', data);
}
self.setOption = function(key, value) {
if (key == 'value') {
setValue();
}
}
// fixme: is this used?
that.getInputById = function(id) {
var input = null;
@ -136,19 +160,6 @@ Ox.InputGroup = function(options, self) {
return input;
};
that.value = function() {
var values = self.options.inputs.map(function(input) {
var ret = null;
['checked', 'selected', 'value'].forEach(function(v) {
input[v] && (ret = input[v]());
});
return ret;
});
return self.options.joinValues
? self.options.joinValues(values)
: values;
};
return that;
};

View file

@ -9,7 +9,7 @@ Ox.OptionGroup <f> OptionGroup
items <a> array of items
min <n> minimum number of selected items
max <n> maximum number of selected items
property <s|checked> property to check
property <s|'checked'> property to check
@*/
Ox.OptionGroup = function(items, min, max, property) {
@ -36,28 +36,20 @@ Ox.OptionGroup = function(items, min, max, property) {
function getNumber() {
// returns the number of checked items
var num = 0;
items.forEach(function(item) {
if (item[property]) {
num++;
}
});
return num;
return items.reduce(function(prev, curr) {
return prev + curr[property];
}, 0);
}
/*@
[property] <f> returns an array with the positions of all checked item
() -> <a> returns checked items
[property] <f> returns an array with the positions of all checked items
() -> <a> positions of checked items
@*/
// FIXME: isn't value more useful in all cases?
this[property] = function() {
// returns an array with the positions of all checked item
var checked = [];
items.forEach(function(item, i) {
if (item[property]) {
checked.push(i);
}
})
return checked;
return Ox.map(items, function(item, i) {
return item[property] ? i : null;
});
};
/*@
@ -115,6 +107,13 @@ Ox.OptionGroup = function(items, min, max, property) {
return toggled;
}
this.value = function() {
var value = Ox.map(items, function(item) {
return item[property] ? item.id : null;
});
return max == 1 ? (value.length ? value[0] : '') : value;
};
return this;
}

View file

@ -1,26 +1,30 @@
// vim: et:ts=4:sw=4:sts=4:ft=javascript
'use strict';
/*@
Ox.Range <f:Ox.Element> Range Object
() -> <f> Range Object
(options) -> <f> Range Object
(options, self) -> <f> Range Object
options <o> Options object
arrows <b> if true, show arrows
arrowStep <n> step when clicking arrows
arrowSymbols <a> arrow symbols, like ['minus', 'plus']
max <n> maximum value
min <n> minimum value
orientation <s> 'horizontal' or 'vertical'
step <n> step between values
size <n> width or height, in px
thumbSize <n> minimum width or height of thumb, in px
thumbValue <b> if true, display value on thumb
trackGradient <a> colors
trackImages <s|[s]> one or multiple track background image URLs
trackStep <n> 0 (scroll here) or step when clicking track
value <n> initial value
valueNames <a> value names to display on thumb
arrows <b> if true, show arrows
arrowStep <n> step when clicking arrows
arrowSymbols <[s]> arrow symbols, like ['minus', 'plus']
max <n> maximum value
min <n> minimum value
orientation <s> 'horizontal' or 'vertical'
step <n> step between values
size <n> width or height, in px
thumbSize <n> minimum width or height of thumb, in px
thumbStyle <s|'opaque'> Thumb style ('opaque' or 'transparent')
thumbValue <b> if true, display value on thumb
trackColors <[s]> CSS colors
trackGradient <b|false> if true, display track colors as gradient
trackImages <s|[s]> one or multiple track background image URLs
trackStep <n> 0 (scroll here) or step when clicking track
value <n> initial value
values <[s]> values to display on thumb
self <o> shared private variable
change <!> triggered on change of the range
@*/
@ -29,40 +33,51 @@ Ox.Range = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
arrows: false,
arrowStep: 1,
arrowSymbols: ['left', 'right'],
changeOnDrag: true,
max: 100,
min: 0,
orientation: 'horizontal',
step: 1,
size: 128, // fixme: shouldn't this be width?
thumbSize: 16,
thumbValue: false,
trackColors: [],
trackImages: [],
trackStep: 0,
value: 0,
valueNames: null,
})
.options(options || {})
.addClass('OxRange')
.css({
width: self.options.size + 'px'
});
.defaults({
arrows: false,
arrowStep: 1,
arrowSymbols: ['left', 'right'],
changeOnDrag: false,
max: 100,
min: 0,
orientation: 'horizontal',
step: 1,
size: 128, // fixme: shouldn't this be width?
thumbSize: 16,
thumbStyle: 'default',
thumbValue: false,
trackColors: [],
trackGradient: false,
trackImages: [],
trackStep: 0,
value: 0,
values: [],
})
.options(options || {})
.addClass('OxRange')
.css({
width: self.options.size + 'px'
});
self.hasValues = !Ox.isEmpty(self.options.values);
if (self.hasValues) {
self.options.max = self.options.values.length - 1;
self.options.min = 0;
self.options.step = 1;
self.options.thumbValue = true;
self.options.value = Ox.isNumber(self.options.value)
? self.options.values[self.options.value] : self.options.value;
Ox.print('!!!$!!!', self.options.value)
}
self.options.arrowStep = options.arrowStep || self.options.step;
self.options.trackImages = Ox.isArray(self.options.trackImages)
? self.options.trackImages : [self.options.trackImages];
self.options.trackImages = Ox.toArray(self.options.trackImages);
self.trackColors = self.options.trackColors.length;
self.trackImages = self.options.trackImages.length;
self.values = (
self.options.max - self.options.min + self.options.step
) / self.options.step;
Ox.extend(self, {
trackColors: self.options.trackColors.length,
trackImages: self.options.trackImages.length,
values: (self.options.max - self.options.min + self.options.step) /
self.options.step
});
setSizes();
if (self.options.arrows) {
@ -130,12 +145,11 @@ Ox.Range = function(options, self) {
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')
.addClass('OxThumb' + (
self.options.thumbStyle == 'transparent' ? ' OxTransparent' : ''
))
.appendTo(self.$track);
setThumb();
@ -145,7 +159,8 @@ Ox.Range = function(options, self) {
setValue(
self.options.value
+ self.options.arrowStep * (i == 0 ? -1 : 1) * (data.shiftKey ? 2 : 1),
animate
animate,
true
);
}
@ -156,12 +171,12 @@ Ox.Range = function(options, self) {
left: self.$track.offset().left,
offset: isThumb ? data.clientX - self.$thumb.offset().left - 8 /*self.thumbSize / 2*/ : 0
};
setValue(getVal(data.clientX - self.drag.left - self.drag.offset), !isThumb);
setValue(getValue(data.clientX - self.drag.left - self.drag.offset), !isThumb, true);
}
function dragTrack(data) {
setValue(
getVal(data.clientX - self.drag.left - self.drag.offset),
getValue(data.clientX - self.drag.left - self.drag.offset),
false,
self.options.changeOnDrag
);
@ -169,13 +184,14 @@ Ox.Range = function(options, self) {
function dragendTrack(data) {
self.options.value = void 0;
setValue(getVal(data.clientX - self.drag.left - self.drag.offset));
setValue(getValue(data.clientX - self.drag.left - self.drag.offset), false, true);
}
function getPx(val) {
var pxPerVal = (self.trackSize - self.thumbSize) /
(self.options.max - self.options.min);
return Math.ceil((val - self.options.min) * pxPerVal);
function getPx(value) {
var pxPerValue = (self.trackSize - self.thumbSize)
/ (self.options.max - self.options.min);
value = self.hasValues ? self.options.values.indexOf(value) : value;
return Math.ceil((value - self.options.min) * pxPerValue);
}
/*
@ -184,23 +200,30 @@ Ox.Range = function(options, self) {
}
*/
function getVal(px) {
function getValue(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);
valuePerPx = (self.options.max - self.options.min)
/ (self.trackSize - self.thumbSize),
value = Ox.limit(
self.options.min
+ Math.floor(px * valuePerPx / self.options.step) * self.options.step,
self.options.min,
self.options.max
);
return self.hasValues ? self.options.values[value] : value;
}
function setSizes() {
self.trackSize = self.options.size - self.options.arrows * 32;
self.thumbSize = Math.max(self.trackSize / self.values, self.options.thumbSize);
self.trackImageWidths = self.trackImages == 1 ? [self.trackSize - 16] :
Ox.divideInt(self.trackSize - 2, self.trackImages);
self.trackColorsStart = self.thumbSize / 2 / self.options.size;
self.trackColorsStep = (self.options.size - self.thumbSize) /
(self.trackColors - 1) / self.options.size;
self.trackImageWidths = self.trackImages == 1
? [self.trackSize - 16]
: Ox.divideInt(self.trackSize - 2, self.trackImages);
self.trackColorStart = self.options.trackGradient
? self.thumbSize / 2 / self.options.size : 0;
self.trackColorStep = self.options.trackGradient
? (self.options.size - self.thumbSize) / (self.trackColors - 1) / self.options.size
: 1 / self.trackColors;
that.css({
width: self.options.size + 'px'
});
@ -208,53 +231,57 @@ Ox.Range = function(options, self) {
width: (self.trackSize - 2) + 'px'
});
if (self.$thumb) {
self.$thumb.options({
width: self.thumbSize
});
self.$thumb.options({width: self.thumbSize});
setThumb();
}
}
function setThumb(animate) {
self.$thumb.stop().animate({
marginLeft: (getPx(self.options.value) - 1) + 'px',
marginLeft: getPx(self.options.value) - 1 + 'px',
//width: self.thumbSize + 'px'
}, animate ? 250 : 0, function() {
if (self.options.thumbValue) {
self.$thumb.options({
title: self.options.valueNames
? self.options.valueNames[self.options.value]
: self.options.value
});
}
self.options.thumbValue && self.$thumb.options({
title: self.options.value
});
});
}
function setTrackColors() {
// fixme: remove outdated -webkit format, and add -o
self.$track.css({
backgroundImage: $.browser.mozilla ?
('-moz-linear-gradient(left, ' +
self.options.trackColors[0] + ' 0%, ' + self.options.trackColors.map(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] + '), ' + self.options.trackColors.map(function(v, i) {
return 'color-stop(' + (self.trackColorsStart + self.trackColorsStep * i) + ', ' + v + ')';
}).join(', ') + ', color-stop(1, ' + self.options.trackColors[self.trackColors - 1] + '))')
['moz', 'o', 'webkit'].forEach(function(browser) {
self.$track.css({
background: '-' + browser + '-linear-gradient(left, '
+ self.options.trackColors[0] + ' 0%, '
+ self.options.trackColors.map(function(v, i) {
var ret = v + ' ' + (
self.trackColorStart + self.trackColorStep * i
) * 100 + '%';
if (!self.options.trackGradient) {
ret += ', ' + v + ' ' + (
self.trackColorStart + self.trackColorStep * (i + 1)
) * 100 + '%';
}
return ret;
}).join(', ') + ', '
+ self.options.trackColors[self.trackColors - 1] + ' 100%)'
});
});
}
function setValue(value, animate, trigger) {
// fixme: toPrecision helps with imprecise results of divisions,
// but won't work for very large values. And is 10 a good value?
value = Ox.limit(value.toPrecision(10), self.options.min, self.options.max);
trigger = trigger !== false;
value = Ox.limit(
self.hasValues ? self.options.values.indexOf(value) : value.toPrecision(10),
self.options.min,
self.options.max
);
value = self.hasValues ? self.options.values[value] : value;
if (value != self.options.value) {
//time = getTime(self.options.value, value);
self.options.value = value;
setThumb(animate);
trigger && that.triggerEvent('change', {value: value});
trigger && that.triggerEvent('change', {value: self.options.value});
}
}
@ -268,15 +295,6 @@ Ox.Range = function(options, self) {
}
}
that.value = function() {
if (arguments.length == 0) {
return self.options.value;
} else {
self.options.type = arguments[0];
setThumb();
}
};
return that;
};

View file

@ -10,7 +10,7 @@ Ox.Select <f:Ox.Element> Select Object
options <o> Options object
disabled <b|false> If true, select is disabled
id <s> Element id
items <a|[]> Items
items <a|[]> Items (array of {id, title} or strings)
label <s|''> Label
labelWidth <n|64> Label width
max <n|1> Maximum number of selected items
@ -25,6 +25,7 @@ Ox.Select <f:Ox.Element> Select Object
(e) -> <string> Tooltip title
e <object> Mouse event
type <s|'text'> Type ('text' or 'image')
value <a|s> Selected id, or array of selected ids
width <s|n|'auto'> Width in px, or 'auto'
self <o> Shared private variable
click <!> Click event
@ -33,8 +34,6 @@ Ox.Select <f:Ox.Element> Select Object
Ox.Select = function(options, self) {
// fixme: make selected a separate option
// fixme: selected item needs attribute "checked", not "selected" ... that's strange
self = self || {};
var that = Ox.Element({
tooltip: options.tooltip || ''
@ -47,18 +46,15 @@ Ox.Select = function(options, self) {
max: 1,
maxWidth: 0,
min: 1,
overlap: 'none', // can be none, left or right
selectable: true,
overlap: 'none',
size: 'medium',
style: 'rounded',
title: '',
type: 'text', // can be 'text' or 'image'
value: '',
type: 'text',
value: options.max != 1 ? [] : '',
width: 'auto'
})
// fixme: make default selection restorable
// or allow for extra action items below options
// fixme: passing value has no effect
.options(options)
.addClass(
'OxSelect Ox' + Ox.toTitleCase(self.options.size)
@ -78,15 +74,22 @@ Ox.Select = function(options, self) {
Ox.Log('Form', 'Ox.Select', self.options);
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();
}
self.options.items = self.options.items.map(function(item) {
return {
id: item.id || item,
title: item.title || item,
checked: Ox.toArray(self.options.value).indexOf(item.id || item) > -1
};
});
self.optionGroup = new Ox.OptionGroup(
self.options.items,
self.options.min,
self.options.max,
'checked'
);
self.options.items = self.optionGroup.init();
self.options.value = self.optionGroup.value();
if (self.options.label) {
self.$label = Ox.Label({
@ -95,14 +98,11 @@ Ox.Select = function(options, self) {
title: self.options.label,
width: self.options.labelWidth
})
.click(function() {
// fixme: ???
// that.focus();
})
.appendTo(that);
}
if (self.options.type == 'text') {
Ox.Log('Form', 'S.O.V.', self.options.value)
self.$title = $('<div>')
.addClass('OxTitle')
.css({
@ -110,7 +110,7 @@ Ox.Select = function(options, self) {
})
.html(
self.options.title
|| self.options.items[self.checked[0]].title
|| getItem(self.options.value).title
)
.appendTo(that);
}
@ -127,12 +127,12 @@ Ox.Select = function(options, self) {
self.$menu = Ox.Menu({
element: self.$title || self.$button,
id: self.options.id + 'Menu',
items: [self.options.selectable ? {
items: [{
group: self.options.id + 'Group',
items: self.options.items,
max: self.options.max,
min: self.options.min
} : self.options.items],
}],
maxWidth: self.options.maxWidth,
side: 'bottom', // FIXME: should be edge
size: self.options.size
@ -150,20 +150,18 @@ Ox.Select = function(options, self) {
}
function changeMenu(data) {
//Ox.Log('Form', 'clickMenu: ', self.options.id, data)
if (self.options.selectable) {
self.checked = self.optionGroup.checked();
self.options.value = data.checked.length ? data.checked[0].id : '';
self.$title && self.$title.html(
self.options.title ? self.options.title : data.checked[0].title
);
that.triggerEvent('change', {
selected: data.checked,
value: self.options.value
});
} else {
that.triggerEvent('click', data);
}
self.options.value = self.optionGroup.value();
Ox.Log('Form', 'changeMenu: ', data, 'value:', self.options.value, 'checked:', self.optionGroup.checked())
self.$title && self.$title.html(
self.options.title ? self.options.title : getItem(self.options.value).title
);
that.triggerEvent('change', {
value: self.options.value
});
}
function getItem(id) {
return Ox.getObjectById(self.options.items, id);
}
function getTitleWidth() {
@ -174,16 +172,18 @@ Ox.Select = function(options, self) {
}
function hideMenu() {
//Ox.Log('Form', '%% hideMenu that', that, 'self', self)
that.loseFocus();
that.removeClass('OxSelected');
// self.$button.removeClass('OxSelected');
//Ox.Log('Form', '%% hideMenu end')
}
function loseFocus() {
that.loseFocus();
}
function selectItem() {
}
function showMenu() {
that.gainFocus();
that.addClass('OxSelected');
@ -202,12 +202,18 @@ Ox.Select = function(options, self) {
self.$button.options({title: value});
}
} else if (key == 'width') {
Ox.Log('Form', 'SETTING WIDTH OPTION', value)
Ox.Log('Form', 'SETTING WIDTH OPTION', value);
that.css({width: value - 2 + 'px'});
self.$title.css({width: getTitleWidth() + 'px'});
} else if (key == 'value') {
Ox.Log('Form', 'SETTING VALUE OPTION', value)
that.selectItem(value);
Ox.Log('Form', 'SETTING VALUE OPTION', value);
if (self.options.type == 'text' && !self.options.title) {
self.$title.html(getItem(value).title);
}
Ox.toArray(value).forEach(function(value) {
self.$menu.checkItem(value);
});
self.options.value = self.optionGroup.value();
}
};
@ -225,33 +231,17 @@ Ox.Select = function(options, self) {
self.superRemove();
};
// FIXME: selected() _and_ selectItem() _and_ value() ???
/*@
selected <f> gets selected item
() -> <o> returns object of selected items with id, title
() -> <o> returns array of selected items with id and title
@*/
that.selected = function() {
return self.options.selectable ? self.optionGroup.checked().map(function(v) {
return Ox.toArray(self.optionGroup.value()).map(function(id) {
return {
id: self.options.items[v].id,
title: self.options.items[v].title
id: id,
title: getItem(id).title
};
}) : [];
};
/*@
selectItem <f> select item in group
(id) -> <u> select item by id
id <s> item id
@*/
that.selectItem = function(id) {
Ox.Log('Form', 'selectItem', id, self.options.items, self.options.items.length, Ox.getObjectById(self.options.items, id))
self.options.type == 'text' && self.$title.html(
Ox.getObjectById(self.options.items, id).title
);
self.$menu.checkItem(id);
self.checked = self.optionGroup.checked();
});
};
/*
@ -264,22 +254,6 @@ Ox.Select = function(options, self) {
};
*/
that.value = function() {
var selected;
if (arguments.length == 0) {
selected = that.selected();
return selected.length ? that.selected()[0].id : '';
} else {
that.selectItem(arguments[0]);
return that;
/*
Ox.Log('Form', 'ELSE');
that.selectItem(arguments[0]);
return that;
*/
}
};
return that;
};

View file

@ -3,17 +3,17 @@
Ox.SelectInput = function(options, self) {
var that;
self = Ox.extend(self || {}, {
options: Ox.extend({
inputWidth: 128,
items: [],
label: '',
labelWidth: 128,
max: 0,
max: 1,
min: 1,
placeholder: '',
title: '',
value: options.max == 1 ? '' : [],
width: 384
}, options)
});
@ -28,21 +28,26 @@ Ox.SelectInput = function(options, self) {
max: self.options.max,
min: self.options.min,
title: self.options.title,
value: self.options.value,
width: self.options.width
})
.bindEvent({
change: function(data) {
if (self.options.title) {
self.$select.options({title: data.selected[0].title});
self.$select.options({
title: Ox.getObjectById(self.options.items, data.value).title
});
}
if (data.selected[0].id == self.other) {
self.$select.options({width: self.otherWidth})
.addClass('OxOverlapRight');
self.$input.show();
} else {
if (data.value != self.other) {
self.$select.options({width: self.options.width})
.removeClass('OxOverlapRight')
self.$input.hide();
self.options.value = data.value
} else {
self.$select.options({width: self.otherWidth})
.addClass('OxOverlapRight');
self.$input.show().focusInput(true);
self.options.value = self.$input.options('value');
}
}
});
@ -51,6 +56,12 @@ Ox.SelectInput = function(options, self) {
placeholder: self.options.placeholder,
width: 0
})
.bindEvent({
change: function(data) {
Ox.print('DATA:', data)
self.options.value = data.value;
}
})
.hide();
that = Ox.FormElementGroup({
@ -58,12 +69,19 @@ Ox.SelectInput = function(options, self) {
self.$select,
self.$input
],
join: function(value) {
return value[value[0] == self.other ? 1 : 0]
},
split: function(value) {
return Ox.map(self.options.items, function(item, i) {
return i < item.length - 1 ? item.id : null;
}).indexOf(value) > -1 ? [value, ''] : [self.other, value];
},
width: self.options.width
});
that.value = function() {
return self.$select.value() == self.other
? self.$input.value() : self.$select.value();
self.setOption = function(key, value) {
// ...
};
return that;

View file

@ -18,34 +18,30 @@ Ox.TimeInput <f:Ox.Element> TimeInput Object
Ox.TimeInput = function(options, self) {
// fixme: seconds get set even if options.seconds is false
self = self || {};
var that = Ox.Element({}, self)
.defaults({
ampm: false,
seconds: false,
milliseconds: false,
value: Ox.formatDate(new Date(), '%T'),
///*
width: {
hours: 32,
minutes: 32,
seconds: 32,
milliseconds: 40,
ampm: 32
}
//*/
})
.options(options || {});
var that;
self = Ox.extend(self || {}, {
options: Ox.extend({
ampm: false,
seconds: false,
milliseconds: false,
value: (function() {
var date = new Date();
return Ox.formatDate(
date,
options.seconds || options.milliseconds ? '%T' : '%H:%M'
) + (options.milliseconds ? '.' + Ox.pad(date % 1000, 3) : '');
}()),
width: {
hours: 32,
minutes: 32,
seconds: 32,
milliseconds: 40,
ampm: 32
}
}, 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.options.seconds = self.options.seconds || self.options.milliseconds;
self.$input = {
hours: Ox.Input({
@ -56,7 +52,6 @@ Ox.TimeInput = function(options, self) {
autocompleteReplaceCorrect: true,
id: 'hours',
textAlign: 'right',
value: self.values.hours,
width: self.options.width.hours
}),
minutes: Ox.Input({
@ -67,7 +62,6 @@ Ox.TimeInput = function(options, self) {
autocompleteReplaceCorrect: true,
id: 'minutes',
textAlign: 'right',
value: self.values.minutes,
width: self.options.width.minutes
}),
seconds: Ox.Input({
@ -78,7 +72,6 @@ Ox.TimeInput = function(options, self) {
autocompleteReplaceCorrect: true,
id: 'seconds',
textAlign: 'right',
value: self.values.seconds,
width: self.options.width.seconds
}),
milliseconds: Ox.Input({
@ -89,7 +82,6 @@ Ox.TimeInput = function(options, self) {
autocompleteReplaceCorrect: true,
id: 'milliseconds',
textAlign: 'right',
value: self.values.milliseconds,
width: self.options.width.milliseconds
}),
ampm: Ox.Input({
@ -97,87 +89,89 @@ Ox.TimeInput = function(options, self) {
autocompleteReplace: true,
autocompleteReplaceCorrect: true,
id: 'ampm',
value: self.values.ampm,
width: self.options.width.ampm
})
};
that = Ox.InputGroup(Ox.extend(self.options, {
inputs: Ox.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
] : []),
joinValues: function(values) {
setValue();
return self.options.value;
},
separators: Ox.merge([
{title: ':', width: 8},
], self.options.seconds ? [
{title: ':', width: 8}
] : [], self.options.milliseconds ? [
{title: '.', width: 8}
] : [], self.options.ampm ? [
{title: '', width: 8}
] : []),
width: 0
//width: self.options.width || 128
}), self)
/*.bindEvent('change', setValue)*/;
setValue();
id: self.options.id,
inputs: Ox.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
] : []),
join: join,
separators: Ox.merge([
{title: ':', width: 8},
], self.options.seconds ? [
{title: ':', width: 8}
] : [], self.options.milliseconds ? [
{title: '.', width: 8}
] : [], self.options.ampm ? [
{title: '', width: 8}
] : []),
split: split,
value: self.options.value,
width: 0
}), self);
function getDate() {
return new Date('1970/01/01 ' + (
self.options.milliseconds ?
self.options.value.substr(0, self.options.value.length - 4) :
self.options.value
self.options.milliseconds
? self.options.value.substr(0, self.options.value.length - 4)
: self.options.value
));
}
function getValues() {
self.date = getDate();
var date = getDate();
return {
ampm: Ox.formatDate(self.date, '%p'),
hours: Ox.formatDate(self.date, self.options.ampm ? '%I' : '%H'),
ampm: Ox.formatDate(date, '%p'),
hours: Ox.formatDate(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')
minutes: Ox.formatDate(date, '%M'),
seconds: Ox.formatDate(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.Log('Form', 'SETVALUE', self.options.value);
function join() {
return 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') : ''
)
);
}
function setValues() {
self.values = getValues();
Ox.forEach(self.$input, function(v, k) {
self.$input[k].options({
value: self.values[k]
});
});
function split(value) {
var values = getValues();
return Ox.merge([
values.hours,
values.minutes,
], self.options.seconds ? [
values.seconds
] : [], self.options.milliseconds ? [
values.milliseconds
] : [], self.options.ampm ? [
values.ampm
] : []);
}
self.setOption = function(key, value) {
if (key == 'value') {
setValues();
}
};
return that;
};

View file

@ -31,56 +31,54 @@ Ox.Menu = function(options, self) {
self = self || {};
var that = Ox.Element({}, self)
.defaults({
element: null,
id: '',
items: [],
mainmenu: null,
maxWidth: 0,
offset: {
left: 0,
top: 0
},
parent: null,
selected: -1,
side: 'bottom', // FIXME: should be 'edge'
size: 'medium' // fixme: remove
})
.options(options || {})
.addClass(
'OxMenu Ox' + Ox.toTitleCase(self.options.side) +
' Ox' + Ox.toTitleCase(self.options.size)
)
.bind({
click: click,
mouseenter: mouseenter,
mouseleave: mouseleave,
mousemove: mousemove,
mousewheel: mousewheel
})
.bindEvent({
key_up: selectPreviousItem,
key_down: selectNextItem,
key_left: selectSupermenu,
key_right: selectSubmenu,
key_escape: hideMenu,
key_enter: clickSelectedItem
}),
// menuHeight,
$item; // fixme: used?
.defaults({
element: null,
id: '',
items: [],
mainmenu: null,
maxWidth: 0,
offset: {
left: 0,
top: 0
},
parent: null,
selected: -1,
side: 'bottom', // FIXME: should be 'edge'
size: 'medium' // fixme: remove
})
.options(options || {})
.addClass(
'OxMenu Ox' + Ox.toTitleCase(self.options.side) +
' Ox' + Ox.toTitleCase(self.options.size)
)
.bind({
click: click,
mouseenter: mouseenter,
mouseleave: mouseleave,
mousemove: mousemove,
mousewheel: mousewheel
})
.bindEvent({
key_up: selectPreviousItem,
key_down: selectNextItem,
key_left: selectSupermenu,
key_right: selectSubmenu,
key_escape: hideMenu,
key_enter: clickSelectedItem
});
self.itemHeight = self.options.size == 'small'
? 12 : self.options.size == 'medium' ? 16 : 20;
self.scrollSpeed = 1;
// construct
// render
that.items = [];
that.submenus = {};
that.$scrollbars = [];
that.$top = $('<div>')
.addClass('OxTop')
.appendTo(that.$element);
that.$scrollbars.up = constructScrollbar('up')
that.$scrollbars.up = renderScrollbar('up')
.appendTo(that.$element);
that.$container = $('<div>')
.addClass('OxContainer')
@ -88,8 +86,8 @@ Ox.Menu = function(options, self) {
that.$content = $('<table>')
.addClass('OxContent')
.appendTo(that.$container);
constructItems(self.options.items);
that.$scrollbars.down = constructScrollbar('down')
renderItems(self.options.items);
that.$scrollbars.down = renderScrollbar('down')
.appendTo(that.$element);
that.$bottom = $('<div>')
.addClass('OxBottom')
@ -179,130 +177,6 @@ Ox.Menu = function(options, self) {
}
}
function constructItems(items) {
that.$content.empty();
scrollMenuUp();
self.optionGroups = {};
items.forEach(function(item, i) {
if (item.group) {
items[i] = item.items.map(function(v) {
return Ox.extend(v, {
group: item.group
});
});
self.optionGroups[item.group] = new Ox.OptionGroup(
items[i].filter(function(v) {
return 'id' in v;
}),
'min' in item ? item.min : 1,
'max' in item ? item.max : 1
);
}
});
items = Ox.flatten(items);
that.items = [];
items.forEach(function(item) {
var position;
if ('id' in item) {
that.items.push(
Ox.MenuItem(Ox.extend(item, {
maxWidth: self.options.maxWidth,
menu: that,
position: position = that.items.length
}))
.data('position', position)
.appendTo(that.$content)
); // fixme: jquery bug when passing {position: position}? does not return the object?;
if (item.items) {
that.submenus[item.id] = Ox.Menu({
element: that.items[position],
id: Ox.toCamelCase(self.options.id + '/' + item.id),
items: item.items,
mainmenu: self.options.mainmenu,
offset: {
left: 0,
top: -4
},
parent: that,
side: 'right',
size: self.options.size,
});
}
} else {
that.$content.append(constructSpace());
that.$content.append(constructLine());
that.$content.append(constructSpace());
}
});
if (!that.is(':hidden')) {
that.hideMenu();
that.showMenu();
}
}
function constructLine() {
return $('<tr>').append(
$('<td>', {
'class': 'OxLine',
colspan: 5
})
);
}
function constructScrollbar(direction) {
var interval,
speed = direction == 'up' ? -1 : 1;
return $('<div/>', {
'class': 'OxScrollbar Ox' + Ox.toTitleCase(direction),
html: Ox.UI.symbols['triangle_' + direction],
click: function() { // fixme: do we need to listen to click event?
return false;
},
mousedown: function() {
self.scrollSpeed = 2;
return false;
},
mouseenter: function() {
self.scrollSpeed = 1;
var $otherScrollbar = that.$scrollbars[direction == 'up' ? 'down' : 'up'];
$(this).addClass('OxSelected');
if ($otherScrollbar.is(':hidden')) {
$otherScrollbar.show();
that.$container.height(that.$container.height() - self.itemHeight);
if (direction == 'down') {
that.$content.css({
top: -self.itemHeight + 'px'
});
}
}
scrollMenu(speed);
interval = setInterval(function() {
scrollMenu(speed);
}, 100);
},
mouseleave: function() {
self.scrollSpeed = 1;
$(this).removeClass('OxSelected');
clearInterval(interval);
},
mouseup: function() {
self.scrollSpeed = 1;
return false;
}
});
}
function constructSpace() {
return $('<tr>').append(
$('<td>', {'class': 'OxSpace', colspan: 5})
);
}
function getElement(id) {
// fixme: needed?
return $('#' + Ox.toCamelCase(options.id + '/' + id));
@ -387,6 +261,130 @@ Ox.Menu = function(options, self) {
}
}
function renderItems(items) {
that.$content.empty();
scrollMenuUp();
self.optionGroups = {};
items.forEach(function(item, i) {
if (item.group) {
items[i] = item.items.map(function(v) {
return Ox.extend(v, {
group: item.group
});
});
self.optionGroups[item.group] = new Ox.OptionGroup(
items[i].filter(function(v) {
return 'id' in v;
}),
'min' in item ? item.min : 1,
'max' in item ? item.max : 1
);
}
});
items = Ox.flatten(items);
that.items = [];
items.forEach(function(item) {
var position;
if (!Ox.isEmpty(item)) {
that.items.push(
Ox.MenuItem(Ox.extend(item, {
maxWidth: self.options.maxWidth,
menu: that,
position: position = that.items.length
}))
.data('position', position)
.appendTo(that.$content)
); // fixme: jquery bug when passing {position: position}? does not return the object?;
if (item.items) {
that.submenus[item.id] = Ox.Menu({
element: that.items[position],
id: Ox.toCamelCase(self.options.id + '/' + item.id),
items: item.items,
mainmenu: self.options.mainmenu,
offset: {
left: 0,
top: -4
},
parent: that,
side: 'right',
size: self.options.size,
});
}
} else {
that.$content.append(renderSpace());
that.$content.append(renderLine());
that.$content.append(renderSpace());
}
});
if (!that.is(':hidden')) {
that.hideMenu();
that.showMenu();
}
}
function renderLine() {
return $('<tr>').append(
$('<td>', {
'class': 'OxLine',
colspan: 5
})
);
}
function renderScrollbar(direction) {
var interval,
speed = direction == 'up' ? -1 : 1;
return $('<div/>', {
'class': 'OxScrollbar Ox' + Ox.toTitleCase(direction),
html: Ox.UI.symbols['triangle_' + direction],
click: function() { // fixme: do we need to listen to click event?
return false;
},
mousedown: function() {
self.scrollSpeed = 2;
return false;
},
mouseenter: function() {
self.scrollSpeed = 1;
var $otherScrollbar = that.$scrollbars[direction == 'up' ? 'down' : 'up'];
$(this).addClass('OxSelected');
if ($otherScrollbar.is(':hidden')) {
$otherScrollbar.show();
that.$container.height(that.$container.height() - self.itemHeight);
if (direction == 'down') {
that.$content.css({
top: -self.itemHeight + 'px'
});
}
}
scrollMenu(speed);
interval = setInterval(function() {
scrollMenu(speed);
}, 100);
},
mouseleave: function() {
self.scrollSpeed = 1;
$(this).removeClass('OxSelected');
clearInterval(interval);
},
mouseup: function() {
self.scrollSpeed = 1;
return false;
}
});
}
function renderSpace() {
return $('<tr>').append(
$('<td>', {'class': 'OxSpace', colspan: 5})
);
}
function scrollMenu(speed) {
var containerHeight = that.$container.height(),
contentHeight = that.$content.height(),
@ -550,7 +548,7 @@ Ox.Menu = function(options, self) {
self.setOption = function(key, value) {
if (key == 'items') {
constructItems(value);
renderItems(value);
} else if (key == 'selected') {
that.$content.find('.OxSelected').removeClass('OxSelected');
selectItem(value);

View file

@ -247,8 +247,6 @@ Forms
background: -moz-linear-gradient(top, rgb(160, 160, 160), rgb(192, 192, 192));
background: -o-linear-gradient(top, rgb(160, 160, 160), rgb(192, 192, 192));
background: -webkit-linear-gradient(top, rgb(160, 160, 160), rgb(192, 192, 192));
//background: -moz-linear-gradient(top, rgb(128, 128, 128), rgb(160, 160, 160) 10%, rgb(192, 192, 192));
//background: -webkit-gradient(linear, left top, left bottom, from(rgb(128, 128, 128)), color-stop(0.1, rgb(160, 160, 160)), to(rgb(192, 192, 192)));
color: rgb(32, 32, 32);
}