diff --git a/demos/arrayinput/js/arrayinput.js b/demos/arrayinput/js/arrayinput.js index e1da3bf9..f80cddff 100644 --- a/demos/arrayinput/js/arrayinput.js +++ b/demos/arrayinput/js/arrayinput.js @@ -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' }) diff --git a/demos/form2/js/form.js b/demos/form2/js/form.js index 943badad..ee71c409 100644 --- a/demos/form2/js/form.js +++ b/demos/form2/js/form.js @@ -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 = $("
").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: $('
') + .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, '
') + .replace(/\s/g, ' ') + ), + 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: $('
').css({margin: '16px'}).html(Ox.isUndefined(value) ? "undefined" : value), - height: 128, - id: "value", + content: $('
') + .css({margin: '16px'}) + .html( + Ox.isUndefined(value) + ? "undefined" + : JSON.stringify(value, void 0, 4) + .replace(/\n/g, '
') + .replace(/\s/g, ' ') + ), + height: 256, title: "Value", - width: 256 + width: 384 }) .open(); }) diff --git a/demos/form2/png/blue.png b/demos/form2/png/blue.png deleted file mode 100644 index 2d9dec38..00000000 Binary files a/demos/form2/png/blue.png and /dev/null differ diff --git a/demos/form2/png/cyan.png b/demos/form2/png/cyan.png deleted file mode 100644 index 797f1102..00000000 Binary files a/demos/form2/png/cyan.png and /dev/null differ diff --git a/demos/form2/png/green.png b/demos/form2/png/green.png deleted file mode 100644 index 8d3f710e..00000000 Binary files a/demos/form2/png/green.png and /dev/null differ diff --git a/demos/form2/png/magenta.png b/demos/form2/png/magenta.png deleted file mode 100644 index 6e616901..00000000 Binary files a/demos/form2/png/magenta.png and /dev/null differ diff --git a/demos/form2/png/red.png b/demos/form2/png/red.png deleted file mode 100644 index 9a79a465..00000000 Binary files a/demos/form2/png/red.png and /dev/null differ diff --git a/demos/form2/png/timeline.png b/demos/form2/png/timeline.png deleted file mode 100644 index d8813cc1..00000000 Binary files a/demos/form2/png/timeline.png and /dev/null differ diff --git a/demos/form2/png/yellow.png b/demos/form2/png/yellow.png deleted file mode 100644 index 92b515ff..00000000 Binary files a/demos/form2/png/yellow.png and /dev/null differ diff --git a/source/Ox.UI/css/Ox.UI.css b/source/Ox.UI/css/Ox.UI.css index 84dba599..52a37d27 100644 --- a/source/Ox.UI/css/Ox.UI.css +++ b/source/Ox.UI/css/Ox.UI.css @@ -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; } /* -------------------------------------------------------------------------------- diff --git a/source/Ox.UI/js/Core/Ox.Element.js b/source/Ox.UI/js/Core/Ox.Element.js index f3f56a8a..70762bde 100644 --- a/source/Ox.UI/js/Core/Ox.Element.js +++ b/source/Ox.UI/js/Core/Ox.Element.js @@ -328,16 +328,23 @@ Ox.Element = function(options, self) { }; /*@ - defaults Sets the default options for an element object + defaults Gets or sets the default options for an element object ({key: value, ...}) -> This element object key The name of the default option value 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 Removes an element object and its event handler () -> 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 Triggers an event (event) -> This element object diff --git a/source/Ox.UI/js/Form/Ox.ArrayInput.js b/source/Ox.UI/js/Form/Ox.ArrayInput.js index 0f464040..2c07880f 100644 --- a/source/Ox.UI/js/Form/Ox.ArrayInput.js +++ b/source/Ox.UI/js/Form/Ox.ArrayInput.js @@ -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; }; \ No newline at end of file diff --git a/source/Ox.UI/js/Form/Ox.Button.js b/source/Ox.UI/js/Form/Ox.Button.js index 85c402d3..0ab0c8b3 100644 --- a/source/Ox.UI/js/Form/Ox.Button.js +++ b/source/Ox.UI/js/Form/Ox.Button.js @@ -1,5 +1,7 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript + 'use strict'; + /*@ Ox.Button Button Object () -> Button Object @@ -11,17 +13,16 @@ Ox.Button Button Object id: button id overlap overlap selectable is selecatable - selected is selected size button size style // can be default, checkbox, symbol, or tab - title title, can be array of titles - tooltip tooltip if multiple must be same number as titles + title title, can be array + tooltip tooltip, can be array (per title) type button type, text or image, (for image, title must be symbolTitle.svg must be availabe) + value is selected width button width self 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 - () -> toggle disabled state - @*/ - that.toggleDisabled = function() { - that.options({ - disabled: !self.options.disabled - }); - return that; - //self.options.disabled = !self.options.disabled; - } - - /*@ - toggleSelected - () -> 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 - () -> toggle through titles + () -> 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({ diff --git a/source/Ox.UI/js/Form/Ox.ButtonGroup.js b/source/Ox.UI/js/Form/Ox.ButtonGroup.js index e29380f0..61764ec7 100644 --- a/source/Ox.UI/js/Form/Ox.ButtonGroup.js +++ b/source/Ox.UI/js/Form/Ox.ButtonGroup.js @@ -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; }; diff --git a/source/Ox.UI/js/Form/Ox.Checkbox.js b/source/Ox.UI/js/Form/Ox.Checkbox.js index ce8674ab..53675580 100644 --- a/source/Ox.UI/js/Form/Ox.Checkbox.js +++ b/source/Ox.UI/js/Form/Ox.Checkbox.js @@ -6,16 +6,16 @@ Ox.Checkbox Checkbox Element (options) -> Checkbox Element (options, self) -> Checkbox Element options Options object - checked if true, checkbox is checked disabled if true, checkbox is disabled group if true, checkbox is part of a group id element id label Label (on the left side) labelWidth Label width title Title (on the right side) + value if true, checkbox is checked width width in px self 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 get current checked state - () -> returns self.options.checked - @*/ - that.checked = function() { - return self.options.checked; - } - - /*@ - toggleChecked toggle current checked state - () -> 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; diff --git a/source/Ox.UI/js/Form/Ox.CheckboxGroup.js b/source/Ox.UI/js/Form/Ox.CheckboxGroup.js index 4bb2e8e1..dae4e0f5 100644 --- a/source/Ox.UI/js/Form/Ox.CheckboxGroup.js +++ b/source/Ox.UI/js/Form/Ox.CheckboxGroup.js @@ -1,5 +1,7 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript + 'use strict'; + /*@ Ox.CheckboxGroup CheckboxGroup Object () -> CheckboxGroup Object @@ -13,7 +15,7 @@ Ox.CheckboxGroup CheckboxGroup Object width width in px self 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; }); diff --git a/source/Ox.UI/js/Form/Ox.ColorInput.js b/source/Ox.UI/js/Form/Ox.ColorInput.js index 96594593..d7c10f9d 100644 --- a/source/Ox.UI/js/Form/Ox.ColorInput.js +++ b/source/Ox.UI/js/Form/Ox.ColorInput.js @@ -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(', ') + ')' }); } diff --git a/source/Ox.UI/js/Form/Ox.ColorPicker.js b/source/Ox.UI/js/Form/Ox.ColorPicker.js index 18d3c041..76063bd6 100644 --- a/source/Ox.UI/js/Form/Ox.ColorPicker.js +++ b/source/Ox.UI/js/Form/Ox.ColorPicker.js @@ -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({ diff --git a/source/Ox.UI/js/Form/Ox.DateInput.js b/source/Ox.UI/js/Form/Ox.DateInput.js index b584bd07..97134bcc 100644 --- a/source/Ox.UI/js/Form/Ox.DateInput.js +++ b/source/Ox.UI/js/Form/Ox.DateInput.js @@ -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; diff --git a/source/Ox.UI/js/Form/Ox.DateTimeInput.js b/source/Ox.UI/js/Form/Ox.DateTimeInput.js index 08722a45..ab1a8ed5 100644 --- a/source/Ox.UI/js/Form/Ox.DateTimeInput.js +++ b/source/Ox.UI/js/Form/Ox.DateTimeInput.js @@ -17,47 +17,55 @@ Ox.DateTimeInput 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; diff --git a/source/Ox.UI/js/Form/Ox.FormElementGroup.js b/source/Ox.UI/js/Form/Ox.FormElementGroup.js index 045cee1d..f90efed6 100644 --- a/source/Ox.UI/js/Form/Ox.FormElementGroup.js +++ b/source/Ox.UI/js/Form/Ox.FormElementGroup.js @@ -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) { diff --git a/source/Ox.UI/js/Form/Ox.Input.js b/source/Ox.UI/js/Form/Ox.Input.js index 21574366..84f34048 100644 --- a/source/Ox.UI/js/Form/Ox.Input.js +++ b/source/Ox.UI/js/Form/Ox.Input.js @@ -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') diff --git a/source/Ox.UI/js/Form/Ox.InputGroup.js b/source/Ox.UI/js/Form/Ox.InputGroup.js index c8f38163..9c919452 100644 --- a/source/Ox.UI/js/Form/Ox.InputGroup.js +++ b/source/Ox.UI/js/Form/Ox.InputGroup.js @@ -18,16 +18,24 @@ Ox.InputGroup 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; }; diff --git a/source/Ox.UI/js/Form/Ox.OptionGroup.js b/source/Ox.UI/js/Form/Ox.OptionGroup.js index eaa3c2e7..b3bb0c1a 100644 --- a/source/Ox.UI/js/Form/Ox.OptionGroup.js +++ b/source/Ox.UI/js/Form/Ox.OptionGroup.js @@ -9,7 +9,7 @@ Ox.OptionGroup OptionGroup items array of items min minimum number of selected items max maximum number of selected items - property property to check + property 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] returns an array with the positions of all checked item - () -> returns checked items + [property] returns an array with the positions of all checked items + () -> 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; } diff --git a/source/Ox.UI/js/Form/Ox.Range.js b/source/Ox.UI/js/Form/Ox.Range.js index 81ecc392..4c2b7694 100644 --- a/source/Ox.UI/js/Form/Ox.Range.js +++ b/source/Ox.UI/js/Form/Ox.Range.js @@ -1,26 +1,30 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript + 'use strict'; + /*@ Ox.Range Range Object () -> Range Object (options) -> Range Object (options, self) -> Range Object options Options object - arrows if true, show arrows - arrowStep step when clicking arrows - arrowSymbols arrow symbols, like ['minus', 'plus'] - max maximum value - min minimum value - orientation 'horizontal' or 'vertical' - step step between values - size width or height, in px - thumbSize minimum width or height of thumb, in px - thumbValue if true, display value on thumb - trackGradient colors - trackImages one or multiple track background image URLs - trackStep 0 (scroll here) or step when clicking track - value initial value - valueNames value names to display on thumb + arrows if true, show arrows + arrowStep step when clicking arrows + arrowSymbols <[s]> arrow symbols, like ['minus', 'plus'] + max maximum value + min minimum value + orientation 'horizontal' or 'vertical' + step step between values + size width or height, in px + thumbSize minimum width or height of thumb, in px + thumbStyle Thumb style ('opaque' or 'transparent') + thumbValue if true, display value on thumb + trackColors <[s]> CSS colors + trackGradient if true, display track colors as gradient + trackImages one or multiple track background image URLs + trackStep 0 (scroll here) or step when clicking track + value initial value + values <[s]> values to display on thumb self 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; }; diff --git a/source/Ox.UI/js/Form/Ox.Select.js b/source/Ox.UI/js/Form/Ox.Select.js index ee69751f..0b449c48 100644 --- a/source/Ox.UI/js/Form/Ox.Select.js +++ b/source/Ox.UI/js/Form/Ox.Select.js @@ -10,7 +10,7 @@ Ox.Select Select Object options Options object disabled If true, select is disabled id Element id - items Items + items Items (array of {id, title} or strings) label Label labelWidth Label width max Maximum number of selected items @@ -25,6 +25,7 @@ Ox.Select Select Object (e) -> Tooltip title e Mouse event type Type ('text' or 'image') + value Selected id, or array of selected ids width Width in px, or 'auto' self Shared private variable click Click event @@ -33,8 +34,6 @@ Ox.Select 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 = $('
') .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 gets selected item - () -> returns object of selected items with id, title + () -> 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 select item in group - (id) -> select item by id - id 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; }; diff --git a/source/Ox.UI/js/Form/Ox.SelectInput.js b/source/Ox.UI/js/Form/Ox.SelectInput.js index c1a81097..8bc4db5f 100644 --- a/source/Ox.UI/js/Form/Ox.SelectInput.js +++ b/source/Ox.UI/js/Form/Ox.SelectInput.js @@ -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; diff --git a/source/Ox.UI/js/Form/Ox.TimeInput.js b/source/Ox.UI/js/Form/Ox.TimeInput.js index 90fe7c58..f25c6a32 100644 --- a/source/Ox.UI/js/Form/Ox.TimeInput.js +++ b/source/Ox.UI/js/Form/Ox.TimeInput.js @@ -18,34 +18,30 @@ Ox.TimeInput 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; }; diff --git a/source/Ox.UI/js/Menu/Ox.Menu.js b/source/Ox.UI/js/Menu/Ox.Menu.js index 53a99e0a..3f8baff2 100644 --- a/source/Ox.UI/js/Menu/Ox.Menu.js +++ b/source/Ox.UI/js/Menu/Ox.Menu.js @@ -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 = $('
') .addClass('OxTop') .appendTo(that.$element); - that.$scrollbars.up = constructScrollbar('up') + that.$scrollbars.up = renderScrollbar('up') .appendTo(that.$element); that.$container = $('
') .addClass('OxContainer') @@ -88,8 +86,8 @@ Ox.Menu = function(options, self) { that.$content = $('') .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 = $('
') .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 $('
').append( - $('').append( - $('').append( + $('').append( + $('
', { - 'class': 'OxLine', - colspan: 5 - }) - ); - } - - function constructScrollbar(direction) { - var interval, - speed = direction == 'up' ? -1 : 1; - return $('
', { - '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 $('
', {'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 $('
', { + 'class': 'OxLine', + colspan: 5 + }) + ); + } + + function renderScrollbar(direction) { + var interval, + speed = direction == 'up' ? -1 : 1; + return $('
', { + '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 $('
', {'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); diff --git a/source/Ox.UI/themes/classic/css/classic.css b/source/Ox.UI/themes/classic/css/classic.css index 5183a82d..3cd8c296 100644 --- a/source/Ox.UI/themes/classic/css/classic.css +++ b/source/Ox.UI/themes/classic/css/classic.css @@ -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); }