[IMP] autocompletion interface (more similar to SearchFacet attributes), correctly document that
bzr revid: xmo@openerp.com-20120321092847-hjsn23ytttzy75ny
This commit is contained in:
parent
248c91d9dd
commit
c3b181d7f3
|
@ -154,8 +154,15 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
|
||||||
var $item = $( "<li></li>" )
|
var $item = $( "<li></li>" )
|
||||||
.data( "item.autocomplete", item )
|
.data( "item.autocomplete", item )
|
||||||
.appendTo( ul );
|
.appendTo( ul );
|
||||||
if (item.type === 'section') {
|
|
||||||
$item.text(item.label)
|
if ('value' in item) {
|
||||||
|
// regular completion item
|
||||||
|
$item.append(
|
||||||
|
('label' in item)
|
||||||
|
? $('<a>').html(item.label)
|
||||||
|
: $('<a>').text(item.value));
|
||||||
|
} else {
|
||||||
|
$item.text(item.category)
|
||||||
.css({
|
.css({
|
||||||
borderTop: '1px solid #cccccc',
|
borderTop: '1px solid #cccccc',
|
||||||
margin: 0,
|
margin: 0,
|
||||||
|
@ -165,11 +172,6 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
|
||||||
clear: 'left',
|
clear: 'left',
|
||||||
width: '100%'
|
width: '100%'
|
||||||
});
|
});
|
||||||
} else if (item.type === 'base') {
|
|
||||||
// FIXME: translation
|
|
||||||
$item.append("<a>Search for: \"<strong>" + item.value + "</strong>\"</a>");
|
|
||||||
} else {
|
|
||||||
$item.append($("<a>").text(item.label));
|
|
||||||
}
|
}
|
||||||
return $item;
|
return $item;
|
||||||
}
|
}
|
||||||
|
@ -182,7 +184,15 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
|
||||||
* @param {Function} resp response callback
|
* @param {Function} resp response callback
|
||||||
*/
|
*/
|
||||||
complete_global_search: function (req, resp) {
|
complete_global_search: function (req, resp) {
|
||||||
var completion = [{value: req.term, type: 'base'}];
|
var completion = [{
|
||||||
|
category: null,
|
||||||
|
value: req.term,
|
||||||
|
label: _.str.sprintf(_.str.escapeHTML(
|
||||||
|
_t("Search for: %(value)s")), {
|
||||||
|
value: '<strong>' + _.str.escapeHTML(req.term) + '</strong>'
|
||||||
|
}),
|
||||||
|
field: null
|
||||||
|
}];
|
||||||
$.when.apply(null, _(this.inputs).chain()
|
$.when.apply(null, _(this.inputs).chain()
|
||||||
.invoke('complete', req.term)
|
.invoke('complete', req.term)
|
||||||
.value()).then(function () {
|
.value()).then(function () {
|
||||||
|
@ -202,20 +212,8 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
|
||||||
*/
|
*/
|
||||||
select_completion: function (e, ui) {
|
select_completion: function (e, ui) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (ui.item.type === 'base') {
|
this.vs.searchQuery.add(new VS.model.SearchFacet(_.extend(
|
||||||
this.vs.searchQuery.add(new VS.model.SearchFacet({
|
{app: this.vs}, ui.item)));
|
||||||
category: null,
|
|
||||||
value: ui.item.value,
|
|
||||||
app: this.vs
|
|
||||||
}));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.vs.searchQuery.add(new VS.model.SearchFacet({
|
|
||||||
category: ui.item.category,
|
|
||||||
value: ui.item.label,
|
|
||||||
json: ui.item.value,
|
|
||||||
app: this.vs
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1026,12 +1024,16 @@ openerp.web.search.Field = openerp.web.search.Input.extend( /** @lends openerp.w
|
||||||
openerp.web.search.CharField = openerp.web.search.Field.extend( /** @lends openerp.web.search.CharField# */ {
|
openerp.web.search.CharField = openerp.web.search.Field.extend( /** @lends openerp.web.search.CharField# */ {
|
||||||
default_operator: 'ilike',
|
default_operator: 'ilike',
|
||||||
complete: function (value) {
|
complete: function (value) {
|
||||||
// FIXME: formatting
|
var label = _.str.sprintf(_.str.escapeHTML(
|
||||||
var label = _.str.sprintf(_t('Search "%s" for "%s"'),
|
_t("Search %(field)s for: %(value)s")), {
|
||||||
this.attrs.string, value);
|
field: '<em>' + this.attrs.string + '</em>',
|
||||||
return $.when([
|
value: '<strong>' + _.str.escapeHTML(value) + '</strong>'});
|
||||||
{category: this.attrs.name, label: label, value:value}
|
return $.when([{
|
||||||
]);
|
category: this.attrs.string,
|
||||||
|
label: label,
|
||||||
|
value: value,
|
||||||
|
field: this
|
||||||
|
}]);
|
||||||
},
|
},
|
||||||
get_value: function () {
|
get_value: function () {
|
||||||
return this.$element.val();
|
return this.$element.val();
|
||||||
|
@ -1114,14 +1116,16 @@ openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends o
|
||||||
})
|
})
|
||||||
.map(function (sel) {
|
.map(function (sel) {
|
||||||
return {
|
return {
|
||||||
category: self.attrs.name,
|
category: self.attrs.string,
|
||||||
label: sel[1],
|
field: self,
|
||||||
value: sel[0]
|
value: sel[1],
|
||||||
|
json: sel[0]
|
||||||
};
|
};
|
||||||
}).value();
|
}).value();
|
||||||
if (_.isEmpty(results)) { return $.when(null); }
|
if (_.isEmpty(results)) { return $.when(null); }
|
||||||
return $.when.apply(null,
|
return $.when.apply(null, [{
|
||||||
[{type: 'section', label: this.attrs.string}].concat(results));
|
category: this.attrs.name
|
||||||
|
}].concat(results));
|
||||||
},
|
},
|
||||||
facet_for: function (value) {
|
facet_for: function (value) {
|
||||||
var match = _(this.attrs.selection).detect(function (sel) {
|
var match = _(this.attrs.selection).detect(function (sel) {
|
||||||
|
@ -1129,11 +1133,11 @@ openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends o
|
||||||
});
|
});
|
||||||
if (!match) { return $.when(null); }
|
if (!match) { return $.when(null); }
|
||||||
return $.when(new VS.model.SearchFacet({
|
return $.when(new VS.model.SearchFacet({
|
||||||
category: this.attrs.string || this.attrs.name,
|
category: this.attrs.string,
|
||||||
value: match[1],
|
value: match[1],
|
||||||
json: match[0],
|
json: match[0],
|
||||||
field: this,
|
field: this,
|
||||||
app: this.view.vs
|
app: this.view.app
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
get_value: function () {
|
get_value: function () {
|
||||||
|
@ -1241,12 +1245,13 @@ openerp.web.search.ManyToOneField = openerp.web.search.CharField.extend({
|
||||||
context: {}
|
context: {}
|
||||||
}).pipe(function (results) {
|
}).pipe(function (results) {
|
||||||
if (_.isEmpty(results)) { return null; }
|
if (_.isEmpty(results)) { return null; }
|
||||||
return [{type: 'section', label: self.attrs.string}].concat(
|
return [{category: self.attrs.string}].concat(
|
||||||
_(results).map(function (result) {
|
_(results).map(function (result) {
|
||||||
return {
|
return {
|
||||||
category: self.attrs.name,
|
category: self.attrs.string,
|
||||||
label: result[1],
|
value: result[1],
|
||||||
value: result[0]
|
json: result[0],
|
||||||
|
field: self
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1255,7 +1260,7 @@ openerp.web.search.ManyToOneField = openerp.web.search.CharField.extend({
|
||||||
var self = this;
|
var self = this;
|
||||||
if (value instanceof Array) {
|
if (value instanceof Array) {
|
||||||
return $.when(new VS.model.SearchFacet({
|
return $.when(new VS.model.SearchFacet({
|
||||||
category: this.attrs.string || this.attrs.name,
|
category: this.attrs.string,
|
||||||
value: value[1],
|
value: value[1],
|
||||||
json: value[0],
|
json: value[0],
|
||||||
field: this,
|
field: this,
|
||||||
|
@ -1265,7 +1270,7 @@ openerp.web.search.ManyToOneField = openerp.web.search.CharField.extend({
|
||||||
return new openerp.web.Model(this.attrs.relation)
|
return new openerp.web.Model(this.attrs.relation)
|
||||||
.call('name_get', [value], {}).pipe(function (names) {
|
.call('name_get', [value], {}).pipe(function (names) {
|
||||||
return new VS.model.SearchFacet({
|
return new VS.model.SearchFacet({
|
||||||
category: self.attrs.string || self.attrs.name,
|
category: self.attrs.string,
|
||||||
value: names[0][1],
|
value: names[0][1],
|
||||||
json: names[0][0],
|
json: names[0][0],
|
||||||
field: self,
|
field: self,
|
||||||
|
|
|
@ -153,6 +153,45 @@ values. These completion values will then be provided to the global
|
||||||
autocompletion list, implemented via `jquery-ui autocomplete
|
autocompletion list, implemented via `jquery-ui autocomplete
|
||||||
<http://jqueryui.com/demos/autocomplete/>`_.
|
<http://jqueryui.com/demos/autocomplete/>`_.
|
||||||
|
|
||||||
|
Because the search view uses a custom renderer for its completion, it
|
||||||
|
was possible to fix some incompatibilities between the attributes of
|
||||||
|
completion items and VisualSearch's facet model:
|
||||||
|
|
||||||
|
Actual completion items
|
||||||
|
+++++++++++++++++++++++
|
||||||
|
|
||||||
|
These are selectable items, and upon selection are turned into actual
|
||||||
|
search facet objects. They should have all the properties of a search
|
||||||
|
facet (as described above) and can have one more optional property:
|
||||||
|
``label``.
|
||||||
|
|
||||||
|
When rendering an item in the list, the renderer will first try to use
|
||||||
|
the ``label`` property if it exists (``label`` can contain HTML and
|
||||||
|
will be inserted as-is, so it can bold or emphasize some of its
|
||||||
|
elements), if it does not it'll use the ``value`` property.
|
||||||
|
|
||||||
|
.. note:: the ``app`` key should not be specified on completion item,
|
||||||
|
it will be set automatically when the search view creates
|
||||||
|
the facet from the item.
|
||||||
|
|
||||||
|
Section titles
|
||||||
|
++++++++++++++
|
||||||
|
|
||||||
|
A second option is to use section titles. Section titles are similar
|
||||||
|
to completion items but only have a ``category`` property. They will
|
||||||
|
be rendered in a different style and can not be selected in the
|
||||||
|
auto-completion (they will be skipped).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Technically, section title items can have any property they want
|
||||||
|
*as long as they do not have a value property*. A ``value``
|
||||||
|
property set to ``false``, ``null`` or ``undefined`` is **not**
|
||||||
|
equivalent to not having a ``value`` property.
|
||||||
|
|
||||||
|
If an input *may* fetch more than one completion item, it *should*
|
||||||
|
prepend a section title (using its own name) to the completion items.
|
||||||
|
|
||||||
Converting to and from facet objects
|
Converting to and from facet objects
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue