[MERGE] web search lazy autocompletion by ged
Search many2one only when they are slected Remove dependecy on jquery.ui automcomplete.
This commit is contained in:
commit
8de012946b
|
@ -1564,6 +1564,46 @@
|
|||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 300px;
|
||||
background-color: white;
|
||||
border: 1px solid black;
|
||||
z-index: 666;
|
||||
margin-top: 5px;
|
||||
cursor: default;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete ul {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
margin: 5px;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete ul li {
|
||||
padding-left: 20px;
|
||||
text-shadow: 0 0 0 white;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete ul li span:first-child {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete ul li span.oe-expand {
|
||||
cursor: pointer;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete ul li.oe-indent {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete ul li.oe-selection-focus {
|
||||
background-color: #7c7bad;
|
||||
color: white;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete ul li.oe-separator {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
border-top: 1px solid #afafb6;
|
||||
}
|
||||
.openerp .oe_searchview .oe-autocomplete ul li.oe-separator:last-child {
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_searchview_drawer_container {
|
||||
overflow: auto;
|
||||
}
|
||||
|
|
|
@ -1289,6 +1289,39 @@ $sheet-padding: 16px
|
|||
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4)
|
||||
@include radius(2px)
|
||||
|
||||
.oe-autocomplete
|
||||
display: none
|
||||
position: absolute
|
||||
width: 300px
|
||||
background-color: white
|
||||
border: 1px solid black
|
||||
z-index: 666
|
||||
margin-top: 5px
|
||||
cursor: default
|
||||
ul
|
||||
list-style-type: none
|
||||
padding-left: 0
|
||||
margin: 5px
|
||||
li
|
||||
padding-left: 20px
|
||||
text-shadow: 0 0 0 white
|
||||
span:first-child
|
||||
margin-right: 5px
|
||||
span.oe-expand
|
||||
cursor: pointer
|
||||
li.oe-indent
|
||||
margin-left: 20px
|
||||
li.oe-selection-focus
|
||||
background-color: #7c7bad
|
||||
color: white
|
||||
li.oe-separator
|
||||
margin-top: 2px
|
||||
margin-bottom: 2px
|
||||
border-top: 1px solid #afafb6
|
||||
li.oe-separator:last-child
|
||||
display: none
|
||||
|
||||
|
||||
.oe_searchview_drawer_container
|
||||
overflow: auto
|
||||
.oe_searchview_drawer
|
||||
|
|
|
@ -350,7 +350,9 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
e.preventDefault();
|
||||
break;
|
||||
case $.ui.keyCode.RIGHT:
|
||||
this.focusFollowing(e.target);
|
||||
if (!this.autocomplete.is_expandable()) {
|
||||
this.focusFollowing(e.target);
|
||||
}
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
|
@ -484,53 +486,18 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
* Sets up search view's view-wide auto-completion widget
|
||||
*/
|
||||
setup_global_completion: function () {
|
||||
var autocomplete = this.$el.autocomplete({
|
||||
var self = this;
|
||||
|
||||
this.autocomplete = new instance.web.search.AutoComplete(this, {
|
||||
source: this.proxy('complete_global_search'),
|
||||
select: this.proxy('select_completion'),
|
||||
focus: function (e) { e.preventDefault(); },
|
||||
html: true,
|
||||
autoFocus: true,
|
||||
minLength: 1,
|
||||
delay: 250,
|
||||
}).data('autocomplete');
|
||||
|
||||
this.$el.on('input', function () {
|
||||
this.$el.autocomplete('close');
|
||||
}.bind(this));
|
||||
|
||||
// MonkeyPatch autocomplete instance
|
||||
_.extend(autocomplete, {
|
||||
_renderItem: function (ul, item) {
|
||||
// item of completion list
|
||||
var $item = $( "<li></li>" )
|
||||
.data( "item.autocomplete", item )
|
||||
.appendTo( ul );
|
||||
|
||||
if (item.facet !== undefined) {
|
||||
// regular completion item
|
||||
if (item.first) {
|
||||
$item.css('borderTop', '1px solid #cccccc');
|
||||
}
|
||||
return $item.append(
|
||||
(item.label)
|
||||
? $('<a>').html(item.label)
|
||||
: $('<a>').text(item.value));
|
||||
}
|
||||
return $item.text(item.label)
|
||||
.css({
|
||||
borderTop: '1px solid #cccccc',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
zoom: 1,
|
||||
'float': 'left',
|
||||
clear: 'left',
|
||||
width: '100%'
|
||||
});
|
||||
},
|
||||
_value: function() {
|
||||
delay: 0,
|
||||
get_search_string: function () {
|
||||
return self.$('div.oe_searchview_input').text();
|
||||
},
|
||||
width: this.$el.width(),
|
||||
});
|
||||
this.autocomplete.appendTo(this.$el);
|
||||
},
|
||||
/**
|
||||
* Provide auto-completion result for req.term (an array to `resp`)
|
||||
|
@ -546,12 +513,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
.value()).then(function () {
|
||||
resp(_(arguments).chain()
|
||||
.compact()
|
||||
.map(function (completion) {
|
||||
if (completion.length && completion[0].facet !== undefined) {
|
||||
completion[0].first = true;
|
||||
}
|
||||
return completion;
|
||||
})
|
||||
.flatten(true)
|
||||
.value());
|
||||
});
|
||||
|
@ -579,14 +540,9 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
childBlurred: function () {
|
||||
var val = this.$el.val();
|
||||
this.$el.val('');
|
||||
var complete = this.$el.data('autocomplete');
|
||||
if ((val && complete.term === undefined) || complete.previous) {
|
||||
throw new Error("new jquery.ui version altering implementation" +
|
||||
" details relied on");
|
||||
}
|
||||
delete complete.term;
|
||||
this.$el.removeClass('oe_focused')
|
||||
.trigger('blur');
|
||||
this.autocomplete.close();
|
||||
},
|
||||
/**
|
||||
* Call the renderFacets method with the correct arguments.
|
||||
|
@ -890,8 +846,10 @@ instance.web.SearchViewDrawer = instance.web.Widget.extend({
|
|||
filters.push(new instance.web.search.Filter(item, group));
|
||||
break;
|
||||
case 'group':
|
||||
self.add_separator();
|
||||
self.make_widgets(item.children, fields,
|
||||
new instance.web.search.Group(group, 'w', item));
|
||||
self.add_separator();
|
||||
break;
|
||||
case 'field':
|
||||
var field = this.make_field(
|
||||
|
@ -907,6 +865,11 @@ instance.web.SearchViewDrawer = instance.web.Widget.extend({
|
|||
group.push(new instance.web.search.FilterGroup(filters, this));
|
||||
}
|
||||
},
|
||||
|
||||
add_separator: function () {
|
||||
if (!(_.last(this.inputs) instanceof instance.web.search.Separator))
|
||||
new instance.web.search.Separator(this);
|
||||
},
|
||||
/**
|
||||
* Creates a field for the provided field descriptor item (which comes
|
||||
* from fields_view_get)
|
||||
|
@ -1349,6 +1312,15 @@ instance.web.search.Filter = instance.web.search.Input.extend(/** @lends instanc
|
|||
get_context: function () { },
|
||||
get_domain: function () { },
|
||||
});
|
||||
|
||||
instance.web.search.Separator = instance.web.search.Input.extend({
|
||||
_in_drawer: false,
|
||||
|
||||
complete: function () {
|
||||
return {is_separator: true};
|
||||
}
|
||||
});
|
||||
|
||||
instance.web.search.Field = instance.web.search.Input.extend( /** @lends instance.web.search.Field# */ {
|
||||
template: 'SearchView.field',
|
||||
default_operator: '=',
|
||||
|
@ -1639,7 +1611,25 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
|||
this._super(view_section, field, parent);
|
||||
this.model = new instance.web.Model(this.attrs.relation);
|
||||
},
|
||||
complete: function (needle) {
|
||||
|
||||
complete: function (value) {
|
||||
if (_.isEmpty(value)) { return $.when(null); }
|
||||
var label = _.str.sprintf(_.str.escapeHTML(
|
||||
_t("Search %(field)s for: %(value)s")), {
|
||||
field: '<em>' + _.escape(this.attrs.string) + '</em>',
|
||||
value: '<strong>' + _.escape(value) + '</strong>'});
|
||||
return $.when([{
|
||||
label: label,
|
||||
facet: {
|
||||
category: this.attrs.string,
|
||||
field: this,
|
||||
values: [{label: value, value: value}]
|
||||
},
|
||||
expand: this.expand.bind(this),
|
||||
}]);
|
||||
},
|
||||
|
||||
expand: function (needle) {
|
||||
var self = this;
|
||||
// FIXME: "concurrent" searches (multiple requests, mis-ordered responses)
|
||||
var context = instance.web.pyeval.eval(
|
||||
|
@ -1652,13 +1642,12 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
|||
context: context
|
||||
}).then(function (results) {
|
||||
if (_.isEmpty(results)) { return null; }
|
||||
return [{label: self.attrs.string}].concat(
|
||||
_(results).map(function (result) {
|
||||
return {
|
||||
label: _.escape(result[1]),
|
||||
facet: facet_from(self, result)
|
||||
};
|
||||
}));
|
||||
return _(results).map(function (result) {
|
||||
return {
|
||||
label: _.escape(result[1]),
|
||||
facet: facet_from(self, result)
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
facet_for: function (value) {
|
||||
|
@ -2311,6 +2300,213 @@ instance.web.search.custom_filters = new instance.web.Registry({
|
|||
'id': 'instance.web.search.ExtendedSearchProposition.Id'
|
||||
});
|
||||
|
||||
instance.web.search.AutoComplete = instance.web.Widget.extend({
|
||||
template: "SearchView.autocomplete",
|
||||
|
||||
// Parameters for autocomplete constructor:
|
||||
//
|
||||
// parent: this is used to detect keyboard events
|
||||
//
|
||||
// options.source: function ({term:query}, callback). This function will be called to
|
||||
// obtain the search results corresponding to the query string. It is assumed that
|
||||
// options.source will call callback with the results.
|
||||
// options.delay: delay in millisecond before calling source. Useful if you don't want
|
||||
// to make too many rpc calls
|
||||
// options.select: function (ev, {item: {facet:facet}}). Autocomplete widget will call
|
||||
// that function when a selection is made by the user
|
||||
// options.get_search_string: function (). This function will be called by autocomplete
|
||||
// to obtain the current search string.
|
||||
init: function (parent, options) {
|
||||
this._super(parent);
|
||||
this.$input = parent.$el;
|
||||
this.source = options.source;
|
||||
this.delay = options.delay;
|
||||
this.select = options.select,
|
||||
this.get_search_string = options.get_search_string;
|
||||
this.width = options.width || 400;
|
||||
|
||||
this.current_result = null;
|
||||
|
||||
this.searching = true;
|
||||
this.search_string = null;
|
||||
this.current_search = null;
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
this.$el.width(this.width);
|
||||
this.$input.on('keyup', function (ev) {
|
||||
if (ev.which === $.ui.keyCode.RIGHT) {
|
||||
self.searching = true;
|
||||
ev.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (!self.searching) {
|
||||
self.searching = true;
|
||||
return;
|
||||
}
|
||||
self.search_string = self.get_search_string();
|
||||
if (self.search_string.length) {
|
||||
var search_string = self.search_string;
|
||||
setTimeout(function () { self.initiate_search(search_string);}, self.delay);
|
||||
} else {
|
||||
self.close();
|
||||
}
|
||||
});
|
||||
this.$input.on('keydown', function (ev) {
|
||||
switch (ev.which) {
|
||||
case $.ui.keyCode.TAB:
|
||||
case $.ui.keyCode.ENTER:
|
||||
if (self.get_search_string().length) {
|
||||
self.select_item(ev);
|
||||
}
|
||||
break;
|
||||
case $.ui.keyCode.DOWN:
|
||||
self.move('down');
|
||||
self.searching = false;
|
||||
ev.preventDefault();
|
||||
break;
|
||||
case $.ui.keyCode.UP:
|
||||
self.move('up');
|
||||
self.searching = false;
|
||||
ev.preventDefault();
|
||||
break;
|
||||
case $.ui.keyCode.RIGHT:
|
||||
self.searching = false;
|
||||
var current = self.current_result
|
||||
if (current && current.expand && !current.expanded) {
|
||||
self.expand();
|
||||
self.searching = true;
|
||||
}
|
||||
ev.preventDefault();
|
||||
break;
|
||||
case $.ui.keyCode.ESCAPE:
|
||||
self.close();
|
||||
self.searching = false;
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
initiate_search: function (query) {
|
||||
if (query === this.search_string && query !== this.current_search) {
|
||||
this.search(query);
|
||||
}
|
||||
},
|
||||
search: function (query) {
|
||||
var self = this;
|
||||
this.current_search = query;
|
||||
this.source({term:query}, function (results) {
|
||||
if (results.length) {
|
||||
self.render_search_results(results);
|
||||
self.focus_element(self.$('li:first-child'));
|
||||
} else {
|
||||
self.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
render_search_results: function (results) {
|
||||
var self = this;
|
||||
var $list = this.$('ul');
|
||||
$list.empty();
|
||||
var render_separator = false;
|
||||
results.forEach(function (result) {
|
||||
if (result.is_separator) {
|
||||
if (render_separator)
|
||||
$list.append($('<li>').addClass('oe-separator'));
|
||||
render_separator = false;
|
||||
} else {
|
||||
var $item = self.make_list_item(result).appendTo($list);
|
||||
result.$el = $item;
|
||||
render_separator = true;
|
||||
}
|
||||
});
|
||||
this.show();
|
||||
},
|
||||
make_list_item: function (result) {
|
||||
var self = this;
|
||||
var $li = $('<li>')
|
||||
.hover(function (ev) {self.focus_element($li);})
|
||||
.mousedown(function (ev) {
|
||||
if (ev.button === 0) { // left button
|
||||
self.select(ev, {item: {facet: result.facet}});
|
||||
self.close();
|
||||
} else {
|
||||
ev.preventDefault();
|
||||
}
|
||||
})
|
||||
.data('result', result);
|
||||
if (result.expand) {
|
||||
var $expand = $('<span class="oe-expand">').text('▶').appendTo($li);
|
||||
$expand.mousedown(function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
if (result.expanded)
|
||||
self.fold();
|
||||
else
|
||||
self.expand();
|
||||
});
|
||||
result.expanded = false;
|
||||
}
|
||||
if (result.indent) $li.addClass('oe-indent');
|
||||
$li.append($('<span>').html(result.label));
|
||||
return $li;
|
||||
},
|
||||
expand: function () {
|
||||
var self = this;
|
||||
this.current_result.expand(this.get_search_string()).then(function (results) {
|
||||
(results || [{label: '(no result)'}]).reverse().forEach(function (result) {
|
||||
result.indent = true;
|
||||
var $li = self.make_list_item(result);
|
||||
self.current_result.$el.after($li);
|
||||
});
|
||||
self.current_result.expanded = true;
|
||||
self.current_result.$el.find('span.oe-expand').html('▼');
|
||||
});
|
||||
},
|
||||
fold: function () {
|
||||
var $next = this.current_result.$el.next();
|
||||
while ($next.hasClass('oe-indent')) {
|
||||
$next.remove();
|
||||
$next = this.current_result.$el.next();
|
||||
}
|
||||
this.current_result.expanded = false;
|
||||
this.current_result.$el.find('span.oe-expand').html('▶');
|
||||
},
|
||||
focus_element: function ($li) {
|
||||
this.$('li').removeClass('oe-selection-focus');
|
||||
$li.addClass('oe-selection-focus');
|
||||
this.current_result = $li.data('result');
|
||||
},
|
||||
select_item: function (ev) {
|
||||
if (this.current_result.facet) {
|
||||
this.select(ev, {item: {facet: this.current_result.facet}});
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
show: function () {
|
||||
this.$el.show();
|
||||
},
|
||||
close: function () {
|
||||
this.current_search = null;
|
||||
this.search_string = null;
|
||||
this.searching = true;
|
||||
this.$el.hide();
|
||||
},
|
||||
move: function (direction) {
|
||||
var $next;
|
||||
if (direction === 'down') {
|
||||
$next = this.$('li.oe-selection-focus').nextAll(':not(.oe-separator)').first();
|
||||
if (!$next.length) $next = this.$('li:first-child');
|
||||
} else {
|
||||
$next = this.$('li.oe-selection-focus').prevAll(':not(.oe-separator)').first();
|
||||
if (!$next.length) $next = this.$('li:last-child');
|
||||
}
|
||||
this.focus_element($next);
|
||||
},
|
||||
is_expandable: function () {
|
||||
return !!this.$('.oe-selection-focus .oe-expand').length;
|
||||
},
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
|
|
@ -1720,6 +1720,10 @@
|
|||
</select>
|
||||
</t>
|
||||
|
||||
<div t-name="SearchView.autocomplete" class="oe-autocomplete">
|
||||
<ul>
|
||||
</ul>
|
||||
</div>
|
||||
<t t-name="ExportView">
|
||||
<a id="exportview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Export</a>
|
||||
</t>
|
||||
|
|
|
@ -558,7 +558,20 @@ openerp.testing.section('search.completions', {
|
|||
new Date(2012, 4, 21, 21, 21, 21).getTime());
|
||||
});
|
||||
});
|
||||
test("M2O", {asserts: 13}, function (instance, $s, mock) {
|
||||
test("M2O complete", {asserts: 4}, function (instance, $s, mock) {
|
||||
var view = {inputs: [], dataset: {get_context: function () {}}};
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {string: 'Dummy'}}, {relation: 'dummy.model'}, view);
|
||||
return f.complete("bob")
|
||||
.done(function (c) {
|
||||
equal(c.length, 1, "should return one line");
|
||||
var bob = c[0];
|
||||
ok(bob.expand, "should return an expand callback");
|
||||
ok(bob.facet, "should have a facet");
|
||||
ok(bob.label, "should have a label");
|
||||
});
|
||||
});
|
||||
test("M2O expand", {asserts: 11}, function (instance, $s, mock) {
|
||||
mock('dummy.model:name_search', function (args, kwargs) {
|
||||
deepEqual(args, []);
|
||||
strictEqual(kwargs.name, 'bob');
|
||||
|
@ -568,21 +581,18 @@ openerp.testing.section('search.completions', {
|
|||
var view = {inputs: [], dataset: {get_context: function () {}}};
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {string: 'Dummy'}}, {relation: 'dummy.model'}, view);
|
||||
return f.complete("bob")
|
||||
return f.expand("bob")
|
||||
.done(function (c) {
|
||||
equal(c.length, 3, "should return results + title");
|
||||
var title = c[0];
|
||||
equal(title.label, f.attrs.string, "title should match field name");
|
||||
ok(!title.facet, "title should not have a facet");
|
||||
equal(c.length, 2, "should return results");
|
||||
|
||||
var f1 = new instance.web.search.Facet(c[1].facet);
|
||||
equal(c[1].label, "choice 1");
|
||||
var f1 = new instance.web.search.Facet(c[0].facet);
|
||||
equal(c[0].label, "choice 1");
|
||||
equal(f1.get('category'), f.attrs.string);
|
||||
equal(f1.get('field'), f);
|
||||
deepEqual(f1.values.toJSON(), [{label: 'choice 1', value: 42}]);
|
||||
|
||||
var f2 = new instance.web.search.Facet(c[2].facet);
|
||||
equal(c[2].label, "choice @");
|
||||
var f2 = new instance.web.search.Facet(c[1].facet);
|
||||
equal(c[1].label, "choice @");
|
||||
equal(f2.get('category'), f.attrs.string);
|
||||
equal(f2.get('field'), f);
|
||||
deepEqual(f2.values.toJSON(), [{label: 'choice @', value: 43}]);
|
||||
|
@ -597,7 +607,7 @@ openerp.testing.section('search.completions', {
|
|||
var view = {inputs: [], dataset: {get_context: function () {}}};
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {string: 'Dummy'}}, {relation: 'dummy.model'}, view);
|
||||
return f.complete("bob")
|
||||
return f.expand("bob")
|
||||
.done(function (c) {
|
||||
ok(!c, "no match should yield no completion");
|
||||
});
|
||||
|
@ -620,9 +630,9 @@ openerp.testing.section('search.completions', {
|
|||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {string: 'Dummy', domain: '[["foo", "=", "bar"]]'}},
|
||||
{relation: 'dummy.model'}, view);
|
||||
return f.complete("bob");
|
||||
return f.expand("bob");
|
||||
});
|
||||
test("M2O custom operator", {asserts: 10}, function (instance, $s, mock) {
|
||||
test("M2O custom operator", {asserts: 8}, function (instance, $s, mock) {
|
||||
mock('dummy.model:name_search', function (args, kwargs) {
|
||||
deepEqual(args, [], "should have no positional arguments");
|
||||
// the operator is meant for the final search term generation, not the autocompletion
|
||||
|
@ -635,15 +645,12 @@ openerp.testing.section('search.completions', {
|
|||
{attrs: {string: 'Dummy', operator: 'ilike'}},
|
||||
{relation: 'dummy.model'}, view);
|
||||
|
||||
return f.complete('bob')
|
||||
return f.expand('bob')
|
||||
.done(function (c) {
|
||||
equal(c.length, 2, "should return result + title");
|
||||
var title = c[0];
|
||||
equal(title.label, f.attrs.string, "title should match field name");
|
||||
ok(!title.facet, "title should not have a facet");
|
||||
equal(c.length, 1, "should return result");
|
||||
|
||||
var f1 = new instance.web.search.Facet(c[1].facet);
|
||||
equal(c[1].label, "Match");
|
||||
var f1 = new instance.web.search.Facet(c[0].facet);
|
||||
equal(c[0].label, "Match");
|
||||
equal(f1.get('category'), f.attrs.string);
|
||||
equal(f1.get('field'), f);
|
||||
deepEqual(f1.values.toJSON(), [{label: 'Match', value: 42}]);
|
||||
|
@ -1210,13 +1217,14 @@ openerp.testing.section('search.groupby', {
|
|||
var view = makeSearchView(instance);
|
||||
return view.appendTo($fix)
|
||||
.done(function () {
|
||||
// 3 filters, 3 filtergroups, 1 custom filter, 1 advanced, 1 Filters
|
||||
// 3 filters, 3 filtergroups, 1 custom filter, 1 advanced, 1 Filters,
|
||||
// and 1 SaveFilter widget
|
||||
equal(view.drawer.inputs.length, 10, "should have 10 inputs total");
|
||||
|
||||
var groups = _.filter(view.drawer.inputs, function (f) {
|
||||
return f instanceof instance.web.search.GroupbyGroup;
|
||||
});
|
||||
|
||||
equal(groups.length, 3, "should have 3 GroupbyGroups");
|
||||
|
||||
groups[0].toggle(groups[0].filters[0]);
|
||||
|
@ -1549,10 +1557,11 @@ openerp.testing.section('search.invisible', {
|
|||
var done = $.Deferred();
|
||||
view.complete_global_search({term: 'filter'}, function (compls) {
|
||||
done.resolve();
|
||||
strictEqual(compls.length, 2,
|
||||
"should have 2 completions");
|
||||
console.log("completions", compls);
|
||||
strictEqual(compls.length, 5,
|
||||
"should have 5 completions"); // 2 filters and 3 separators
|
||||
deepEqual(_.pluck(compls, 'label'),
|
||||
['Field 0', 'Filter on: Filter 0'],
|
||||
[undefined, 'Field 0', 'Filter on: Filter 0', undefined, undefined],
|
||||
"should complete on field 0 and filter 0");
|
||||
});
|
||||
return done;
|
||||
|
|
Loading…
Reference in New Issue