autocomplete, continued
This commit is contained in:
parent
07ec8f30f7
commit
c533678f44
7 changed files with 308 additions and 82 deletions
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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"),
|
||||
"<span class=\"OxHighlight\">$1</span>"
|
||||
);
|
||||
}
|
||||
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) {
|
||||
|
||||
};
|
||||
|
||||
|
|
BIN
build/png/ox.ui.classic/buttonClear.png
Normal file
BIN
build/png/ox.ui.classic/buttonClear.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
build/png/ox.ui.classic/buttonSelect.png
Normal file
BIN
build/png/ox.ui.classic/buttonSelect.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
|
@ -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"),
|
||||
"<span class=\"OxHighlight\">$1</span>")
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
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") {
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue