diff --git a/build/css/ox.ui.classic.css b/build/css/ox.ui.classic.css index d3209358..fb8b443a 100644 --- a/build/css/ox.ui.classic.css +++ b/build/css/ox.ui.classic.css @@ -58,6 +58,7 @@ Forms color: rgb(64, 64, 64); } .OxThemeClassic .OxButton, +.OxThemeClassic div.OxInput, .OxThemeClassic .OxRange { //background: -moz-linear-gradient(left top, left bottom, from(rgb(192, 192, 192)), to(rgb(160, 160, 160))); //background: -webkit-gradient(linear, left top, left bottom, from(rgb(192, 192, 192)), to(rgb(160, 160, 160))); @@ -89,17 +90,17 @@ Forms border-bottom: 1px solid rgb(192, 192, 192); } -.OxThemeClassic .OxInput, +.OxThemeClassic input.OxInput, .OxThemeClassic .OxTrack { background: -moz-linear-gradient(top, rgb(224, 224, 224), rgb(255, 255, 255)); background: -webkit-gradient(linear, left top, left bottom, from(rgb(224, 224, 224)), to(rgb(255, 255, 255))); } -.OxThemeClassic .OxInput:focus { +.OxThemeClassic input.OxInput:focus { border: 1px solid rgb(160, 160, 160); -moz-box-shadow: 0 0 2px rgb(128, 128, 128); - -webkit-box-shadow: 0 2 4px rgb(128, 128, 128); + -webkit-box-shadow: 0 0 2px rgb(128, 128, 128); } -.OxThemeClassic .OxInput.OxPlaceholder { +.OxThemeClassic input.OxInput.OxPlaceholder { color: rgb(160, 160, 160) } diff --git a/build/css/ox.ui.css b/build/css/ox.ui.css index d25a7944..eecdc261 100644 --- a/build/css/ox.ui.css +++ b/build/css/ox.ui.css @@ -274,6 +274,32 @@ OxButtonGroup } /* -------------------------------------------------------------------------------- +OxInput +-------------------------------------------------------------------------------- +*/ +div.OxInput { + -moz-border-radius: 8px; + -webkit-border-radius: 8px; +} +div.OxInput.OxMedium { + height: 14px; +} +div.OxInput > .OxButton:first-child { + float: left; + margin-top: -1px; +} +div.OxInput > .OxButton:last-child { + float: left; + margin-left: -1px; + margin-top: -1px; +} +input.OxInput { + float: left; + margin-left: -1px; + margin-top: -1px; +} +/* +-------------------------------------------------------------------------------- OxRange -------------------------------------------------------------------------------- */ @@ -319,7 +345,7 @@ OxSelect -------------------------------------------------------------------------------- */ .OxSelect.OxMedium { - padding: 0 8px 0 8px; + } .OxSelect > .OxButton { text-align: left; @@ -331,7 +357,7 @@ OxSelect -webkit-user-select: none; } .OxSelect.OxMedium > .OxSymbol { - margin: -16px 8px 0 8px; + margin: -16px 0 0 8px; } /* diff --git a/build/js/ox.ui.js b/build/js/ox.ui.js index a06256ea..74520f24 100644 --- a/build/js/ox.ui.js +++ b/build/js/ox.ui.js @@ -1530,54 +1530,157 @@ requires */ Ox.Input = function(options, self) { + + /* options: + * autocomplete function, or array of values, or dict with array of values per label or placeholder + * clear boolean, clear button, or not + * highlight boolean, highlight value in autocomplete menu, or not + * id + * label string or array (select) -- label and placeholder are mutually exclusive + * labelWidth integer (px) + * placeholder string or array (select) -- label and placeholder are mutually exclusive + * selected integer, selected label or placeholder + * size "large", "medium" or "small" + * type "text", "password", "textarea", etc. + */ + var self = self || {}, - that = new Ox.Element( - options.type == "textarea" ? "textarea" : "input", self - ) + that = new Ox.Element("div", self) .defaults({ autocomplete: null, + clear: false, + highlight: false, id: "", - placeholder: "", // can be [], will result in select + label: "", + labelWidth: 0, + placeholder: "", + selected: 0, size: "medium", type: "text" }) .options(options || {}) - .attr({ - placeholder: self.options.placeholder + .addClass("OxInput Ox" + Ox.toTitleCase(self.options.size)), + autocomplete; + + if (self.options.label) { + self.options.label = Ox.makeArray(self.options.label); + self.label = self.options.label[0]; + } else if (self.options.placeholder) { + self.options.placeholder = Ox.makeArray(self.options.placeholder); + self.placeholder = self.options.placeholder[0]; + } + if (Ox.isArray(self.options.autocomplete)) { + autocomplete = self.options.autocomplete; + self.options.autocomplete = {}; + self.options.autocomplete[self.placeholder] = autocomplete; + } + + if (self.options.label) { + that.$label = "foo"; + } else if (self.options.placeholder.length > 1) { + that.$select = new Ox.Button({ + style: "symbol", + type: "image", + value: "select" }) - .addClass( - "OxInput Ox" + Ox.toTitleCase(self.options.size) + - " OxPlaceholder" - ) - .focus(focus) - .blur(blur) - .change(change); - if (options.autocomplete) { - self.element = that.$element[0]; - self.menuId = self.options.id + "_menu"; // fixme: we do this in other places ... are we doing it the same way? var name? - self.menu = new Ox.Menu({ + .click(select) + .appendTo(that); + self.placeholderId = self.options.id + "_placeholder"; + self.placeholderMenu = new Ox.Menu({ element: that, - id: self.menuId, + id: self.placeholderId, + items: $.map(self.options.placeholder, function(title, position) { + return { + checked: position == self.options.selected, + id: title.toLowerCase(), + group: self.placeholderId, // fixme: same id, works here, but should be different + title: title + }; + }) + }); + that.bindEvent("change_" + self.placeholderId, changePlaceholder); + } + + that.$input = new Ox.Element( + self.options.type == "textarea" ? "textarea" : "input", self + ) + .attr({ + placeholder: self.placeholder, + type: self.options.type == "textarea" ? null : self.options.type + }) + .addClass( + "OxInput Ox" + Ox.toTitleCase(self.options.size) + + " OxPlaceholder" + ) + .focus(focus) + .blur(blur) + .change(change) + .appendTo(that); + + if (self.options.clear) { + that.$clear = new Ox.Button({ + style: "symbol", + type: "image", + value: "clear" + }) + .click(clear) + .appendTo(that); + } + + if (options.autocomplete) { + self.autocompleteId = self.options.id + "_menu"; // fixme: we do this in other places ... are we doing it the same way? var name? + self.autocompleteMenu = new Ox.Menu({ + element: that, + id: self.autocompleteId, offset: { left: 4, top: 0 }, size: self.options.size }); - that.bindEvent("click_" + self.menuId, onClick); - //that.bindEvent("deselect_" + self.menuId, onDeselect); - //that.bindEvent("select_" + self.menuId, onSelect); + that.bindEvent("click_" + self.autocompleteId, onClick); } - if (options.type != "textarea") { - that.attr({ - type: self.options.type - }); + + that.bindEvent({ + key_enter: submit, + key_escape: cancel + }); + + function autocomplete(value, callback) { + value = value.toLowerCase(); + var items = []; + if (value === "") { + items = self.options.autocomplete[self.placeholder]; + } else { + $.each(self.options.autocomplete[self.placeholder], function(i, item) { + if (item.toLowerCase().indexOf(value) > -1) { + if (self.options.highlight) { + item = item.replace( + new RegExp("(" + value + ")", "ig"), + "$1" + ); + } + items.push(item); + } + }); + } + callback(items); } - function autocomplete(items) { + + function call() { + var value = that.$input.val(); + if (self.options.autocomplete) { + Ox.isFunction(self.options.autocomplete) ? + self.options.autocomplete(value, callback) : + autocomplete(value, callback); + } + } + + function callback(items) { var selected = 0; if (items.length) { items = $.map(items, function(title, position) { - if (that.val().toLowerCase() == Ox.stripTags(title.toLowerCase())) { + if (that.$input.val().toLowerCase() == Ox.stripTags(title.toLowerCase())) { selected = position; } return { @@ -1585,54 +1688,88 @@ requires title: title }; }); - self.menu.options({ + self.placeholderMenu.hideMenu(); + self.autocompleteMenu.options({ items: items, selected: selected }).showMenu(); } else { - self.menu.hideMenu(); + self.autocompleteMenu.hideMenu(); } } + + function cancel() { + that.$input.trigger("blur"); + } + + function clear() { + that.$input.val(""); + } + function change() { } + + function changePlaceholder(event, data) { + Ox.print("cP", event, data); + self.placeholder = data.value; // fixme: could be "title" as well + if (that.$input.is(".OxPlaceholder")) { + that.$input.val(self.placeholder); + } + call(); + } + function blur() { - if (that.val() === "") { - that.addClass("OxPlaceholder").val(that.attr("placeholder")); + that.loseFocus(); + if (that.$input.val() === "") { + that.$input.addClass("OxPlaceholder").val(that.$input.attr("placeholder")); } if (self.options.autocomplete) { $document.unbind("keydown", keypress); $document.unbind("keypress", keypress); } } + function focus() { - if (that.is(".OxPlaceholder")) { - that.val("").removeClass("OxPlaceholder"); + that.gainFocus(); + if (that.$input.is(".OxPlaceholder")) { + that.$input.val("").removeClass("OxPlaceholder"); } if (self.options.autocomplete) { // fixme: different in webkit and firefox (?), see keyboard handler, need generic function $document.bind("keydown", keypress); $document.bind("keypress", keypress); - self.options.autocomplete(that.val(), autocomplete); + Ox.isFunction(self.options.autocomplete) ? + self.options.autocomplete(that.$input.val(), callback) : + autocomplete(that.$input.val(), callback); } } + function keypress(event) { if (event.keyCode != 13) { setTimeout(function() { - var value = that.val(); - if (self.options.autocomplete && value != self.value) { + var value = that.$input.val(); + if (value != self.value) { self.value = value; - self.options.autocomplete(value, autocomplete); + call(); } }, 25); } } + function onClick(event, data) { Ox.print("onClick", data) - that.focus().val(Ox.stripTags(data.title)); - self.menu.hideMenu(); + that.$input.focus().val(Ox.stripTags(data.title)); + self.autocompleteMenu.hideMenu(); + submit(); } + + function select() { + self.placeholderMenu.showMenu(); + } + function selection() { + // fixme: not used! var start, end; if (arguments.length == 0) { return [self.element.selectionStart, self.element.selectionEnd]; @@ -1642,7 +1779,22 @@ requires self.element.setSelectionRange(start, end); } } + + function submit() { + that.$input.trigger("blur"); + that.triggerEvent("submit", that.$input.val()); + } + + that.width = function(value) { + that.$element.width(value); + that.$input.width(value - 2 - self.options.labelWidth - + (self.options.placeholder.length > 1) * 21 - + self.options.clear * 21); + return that; + } + return that; + }; /* @@ -1874,7 +2026,7 @@ requires Ox.Select = function(options, self) { var self = self || {}, - that = new Ox.Element("div", self) + that = new Ox.Element("div", self) // fixme: do we use "div", or {}, or "", by default? .defaults({ id: "", items: [], @@ -1945,7 +2097,7 @@ requires that.width = function(val) { // fixme: silly hack, and won't work for css() - that.$element.width(val); + that.$element.width(val + 16); that.$button.width(val); that.$symbol.width(val); return that; @@ -1982,14 +2134,21 @@ requires Ox.MainMenu = function(options, self) { + /* options: + * extras + * menus + * size + */ + var self = self || {}, that = new Ox.Bar({}, self) .defaults({ + extras: [], menus: [], size: "medium" }) .options(options || {}) - .addClass("OxMainMenu Ox" + Ox.toTitleCase(self.options.size)) // fixme: bar should accept small/medium/large + .addClass("OxMainMenu Ox" + Ox.toTitleCase(self.options.size)) // fixme: bar should accept small/medium/large ... like toolbar .click(click) .mousemove(mousemove); @@ -2067,11 +2226,11 @@ requires }; - that.addMenuAfter = function() { + that.addMenuAfter = function(id) { }; - that.addMenuBefore = function() { + that.addMenuBefore = function(id) { }; diff --git a/build/png/ox.ui.classic/buttonClear.png b/build/png/ox.ui.classic/buttonClear.png new file mode 100644 index 00000000..620e25bd Binary files /dev/null and b/build/png/ox.ui.classic/buttonClear.png differ diff --git a/build/png/ox.ui.classic/buttonSelect.png b/build/png/ox.ui.classic/buttonSelect.png new file mode 100644 index 00000000..28ef8b22 Binary files /dev/null and b/build/png/ox.ui.classic/buttonSelect.png differ diff --git a/demos/test/index.html b/demos/test/index.html index 96b29e51..85b54962 100644 --- a/demos/test/index.html +++ b/demos/test/index.html @@ -290,6 +290,12 @@ type: "text", value: "Foo" }).addClass("margin").appendTo(mainPanel); + Ox.Button({ + selectable: true, + size: size, + type: "text", + value: "Bar" + }).addClass("margin").appendTo(mainPanel); Ox.Select({ id: "select1", items: [ @@ -326,40 +332,74 @@ } ] }).addClass("margin").width(96).appendTo(mainPanel); + Ox.Button({ + selectable: true, + size: size, + type: "text", + value: "Foo" + }).addClass("margin").appendTo(mainPanel); + Ox.Button({ + selectable: true, + size: size, + type: "text", + value: "Bar" + }).addClass("margin").appendTo(mainPanel); Ox.Input({ - id: "state", - autocomplete: function(value, callback) { - value = value.toLowerCase(); - var items = [], - states = [ - "Alabama", "Alaska", "Arizona", "Arkansas", "California", - "Colorado", "Connecticut", "Delaware", "District of Columbia", "Florida", - "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", - "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", - "Maryland", "Massachusetts", "Michigan", "Minnessota", "Mississippi", - "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", - "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", - "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", - "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", - "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", - "Wyoming" - ]; - if (value === "") { - items = states; - } else { - $.each(states, function(i, state) { - if (state.toLowerCase().indexOf(value) > -1) { - items.push(state.replace( - new RegExp("(" + value + ")", "ig"), - "$1") - ); - } - }); - } - callback(items); + autocomplete: { + City: [ + "Albuquerque", + "Austin", + "Baltimore", + "Boston", + "Chicago", + "Cleveland", + "Dallas", + "Denver", + "Detroit", + "El Paso", + "Honululu", + "Houston", + "Kansas City", + "Las Vegas", + "Los Angeles", + "Memphis", + "Miami", + "Minneapolis", + "Nashville", + "New Orleans", + "New York", + "Oklahoma City", + "Philadelphia", + "Phoenix", + "Pittsburgh", + "Portland", + "San Antonio", + "San Diego", + "San Francisco", + "St. Louis", + "St. Paul", + "Seattle", + "Washington" + ], + State: [ + "Alabama", "Alaska", "Arizona", "Arkansas", "California", + "Colorado", "Connecticut", "Delaware", "District of Columbia", "Florida", + "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", + "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", + "Maryland", "Massachusetts", "Michigan", "Minnessota", "Mississippi", + "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", + "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", + "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", + "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", + "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", + "Wyoming" + ] }, - placeholder: "State" - }).addClass("margin").width(96).appendTo(mainPanel); + clear: true, + highlight: true, + id: "citystate", + placeholder: ["City", "State"] + }).addClass("margin").width(128).appendTo(mainPanel); //*/ function switchTheme() { if (Ox.theme() == "classic") { diff --git a/source/psd/buttons.psd b/source/psd/buttons.psd index c307394f..06c894ff 100644 Binary files a/source/psd/buttons.psd and b/source/psd/buttons.psd differ