[MERGE] resource: Search view updates
[odoo/odoo.git] / doc / search-view.rst
1 Search View
2 ===========
3
4 OpenERP Web 6.2 implements a unified facets-based search view instead
5 of the previous form-like search view (composed of buttons and
6 multiple fields). The goal for this change is twofold:
7
8 * Avoid the common issue of users confusing the search view with a
9   form view and trying to create their records through it (or entering
10   all their data, hitting the ``Create`` button expecting their record
11   to be created and losing everything).
12
13 * Improve the looks and behaviors of the view, and the fit within
14   OpenERP Web's new design.
15
16 The faceted search is implemented through a monkey-patched
17 `VisualSearch <http://documentcloud.github.com/visualsearch/>`_
18 [#]_. VisualSearch is based on `Backbone
19 <http://documentcloud.github.com/backbone/>`_ and makes significant
20 use of Backbone's models and views. As a result, understanding the
21 implementation of the OpenERP Web 6.2 search view also requires a
22 basic understanding of Backbone.
23
24 .. note::
25
26     This document may mention *fetching* data. This is a shortcut for
27     "returning a deferred to [whatever is being fetched]". Unless
28     further noted, the function or method may opt to return nothing by
29     fetching ``null`` (which can easily be done by returning
30     ``$.when(null)``, which simply wraps the ``null`` in a Deferred).
31
32 Interaction between the Search View and VisualSearch
33 ----------------------------------------------------
34
35 The core data abstraction in VisualSearch is
36 :js:class:`VS.model.SearchQuery`, a backbone Collection holding
37 instances of the :js:class:`VS.model.SearchFacet` backbone Model.
38
39 Backbone models can hold any number of informal properties interacted
40 with through the :js:func:`~Backbone.Model.get` and
41 :js:func:`~Backbone.Model.set` methods. VisualSearch reserves three
42 such properties for its behavior, these properties *must* be correctly
43 set on all search facets created programmatically:
44
45 ``app``
46   a reference to the VisualSearch instance using this facet. In the
47   search view, this instance is available as the
48   :js:attr:`~openerp.web.SearchView.vs` attribute to the searchview
49   instance.
50
51 ``category``
52   the *name* of the facet, displayed in the first section of a facet
53   view.
54
55 ``value``
56   the *displayed value* of the facet, it is directly printed to the
57   right of the category.
58
59 The search view uses additional keys to store state and data it needs
60 to associate with facet objects:
61
62 ``field``
63   the search field instance which created the facet, used when the
64   search view needs to serialize the facets.
65
66 ``json``
67   the "logical" value of the facet, can be absent if the logical and
68   "printable" values of the facet are the same (e.g. for a basic text
69   field).
70
71   This value may be a complex javascript object such as an array (the
72   name stands for json-compatible value, it is not a JSON-encoded
73   string).
74
75 .. note::
76
77      in order to simplify getting the logical value of a search facet
78      model, :js:class:`VS.model.SearchFacet` has been extended with a
79      :js:func:`~VS.model.SearchFacet.value` method
80
81 Extensions and patches to VisualSearch
82 ++++++++++++++++++++++++++++++++++++++
83
84 .. js:function:: VS.model.SearchFacet.value()
85
86     Bundles the logic of selecting between ``json`` and ``value`` in
87     order to get the logical value of a facet.
88
89 .. js:attribute:: VS.options.callbacks.make_facet
90
91     Called by :js:class:`VS.ui.SearchBox` when it needs to create a
92     new search facet *view*. By default this is not supported by
93     VisualSearch, and requires monkey-patching
94     :js:func:`VS.ui.SearchBox.renderFacet`.
95
96     This patch should not alter any behavior if
97     :js:attr:`~VS.options.callbacks.make_facet` is not used.
98
99 .. js:attribute:: VS.options.callbacks.make_input
100
101     Similar to :js:attr:`~VS.options.callbacks.make_facet`, but called
102     when the :js:class:`~VS.ui.SearchBox` needs to create a search
103     input view. It requires monkey-patching
104     :js:func:`VS.ui.SearchBox.renderSearchInput`.
105
106 Finally, :js:func:`VS.ui.SearchBox.searchEvent` is monkey-patched to
107 get rid of its serialize/load round-tripping of facet data: the
108 additional attributes needed by the search view don't round-trip (at
109 all) so VisualSearch must not load any data from its (fairly
110 simplistic) text-serialization format.
111
112 .. note::
113
114     a second issue is that — as of `commit 3fca87101d`_ — VisualSearch
115     correctly serializes facet categories containing spaces but is
116     unable to load them back in. It also does not handle facets with
117     *empty* categories correctly.
118
119 Loading Defaults
120 ----------------
121
122 After loading the view data, the SearchView will call
123 :js:func:`openerp.web.search.Input.facet_for_defaults` on each of its
124 inputs with the ``defaults`` mapping of key:values (where each key
125 corresponds to an input). This method should look into the
126 ``defaults`` mapping and fetch the field's default value as a
127 :js:class:`~VS.models.SearchFacet` if applicable.
128
129 The default implementation is to check if there is a default value for
130 the current input's name (via
131 :js:attr:`openerp.web.search.Input.attrs.name`) and if there is to
132 convert this value to a :js:class:`~VS.models.SearchFacet` by calling
133 :js:func:`openerp.web.search.Input.facet_for`.
134
135 There is no built-in (default) implementation of
136 :js:func:`openerp.web.search.Input.facet_for`. This method should
137 fetch the :js:class:`~VS.models.SearchFacet` corresponding to the
138 "raw" value passed as argument.
139
140 Providing auto-completion
141 -------------------------
142
143 An important component of the unified search view is the faceted
144 autocompletion pane. In order to provide good user and developer
145 experiences, this pane is pluggable (value-wise): each and every
146 control of the search view can check for (and provide) categorized
147 auto-completions for a given value being typed by the user.
148
149 This is done by implementing
150 :js:func:`openerp.web.search.Input.complete`: the method is provided
151 with a value to complete, and should fetch an ``Array`` of completion
152 values. These completion values will then be provided to the global
153 autocompletion list, implemented via `jquery-ui autocomplete
154 <http://jqueryui.com/demos/autocomplete/>`_.
155
156 Because the search view uses a custom renderer for its completion, it
157 was possible to fix some incompatibilities between the attributes of
158 completion items and VisualSearch's facet model:
159
160 Actual completion items
161 +++++++++++++++++++++++
162
163 These are selectable items, and upon selection are turned into actual
164 search facet objects. They should have all the properties of a search
165 facet (as described above) and can have one more optional property:
166 ``label``.
167
168 When rendering an item in the list, the renderer will first try to use
169 the ``label`` property if it exists (``label`` can contain HTML and
170 will be inserted as-is, so it can bold or emphasize some of its
171 elements), if it does not the ``value`` property will be used.
172
173 .. note:: the ``app`` key should not be specified on completion item,
174           it will be set automatically when the search view creates
175           the facet from the item.
176
177 Section titles
178 ++++++++++++++
179
180 A second kind of completion values is the section titles. Section
181 titles are similar to completion items but only have a ``category``
182 property. They will be rendered in a different style and can not be
183 selected in the auto-completion (they will be skipped).
184
185 .. note::
186
187     Technically, section title items can have any property they want
188     *as long as they do not have a value property*. A ``value``
189     property set to ``false``, ``null`` or ``undefined`` is **not**
190     equivalent to not having a ``value`` property.
191
192 If an input *may* fetch more than one completion item, it *should*
193 prepend a section title (using its own name) to the completion items.
194
195 Converting from facet objects
196 -----------------------------
197
198 Ultimately, the point of the search view is to allow searching. In
199 OpenERP this is done via :ref:`domains <openerpserver:domains>`. On
200 the other hand, the OpenERP Web 6.2 search view's state is modelled
201 after a collection of :js:class:`~VS.model.SearchFacet`, and each
202 field of a search view may have special requirements when it comes to
203 the domains it produces [#]_.
204
205 So there needs to be some way of mapping
206 :js:class:`~VS.model.SearchFacet` objects to OpenERP search data.
207
208 This is done via an input's
209 :js:func:`~openerp.web.search.Input.get_domain` and
210 :js:func:`~openerp.web.search.Input.get_context`. Each takes a
211 :js:class:`~VS.model.SearchFacet` and returns whatever it's supposed
212 to generate (a domain or a context, respectively). Either can return
213 ``null`` if the current value does not map to a domain or context, and
214 can throw an :js:class:`~openerp.web.search.Invalid` exception if the
215 value is not valid at all for the field.
216
217 Converting to facet objects
218 ---------------------------
219
220 Changes
221 -------
222
223 .. todo:: merge in changelog instead
224
225 The displaying of the search view was significantly altered from
226 OpenERP Web 6.1 to OpenERP Web 6.2.
227
228 As a result, while the external API used to interact with the search
229 view does not change many internal details — including the interaction
230 between the search view and its widgets — were significantly altered:
231
232 Internal operations
233 +++++++++++++++++++
234
235 * :js:func:`openerp.web.SearchView.do_clear` has been removed
236 * :js:func:`openerp.web.SearchView.do_toggle_filter` has been removed
237
238 Widgets API
239 +++++++++++
240
241 * :js:func:`openerp.web.search.Widget.render` has been removed
242
243 * :js:func:`openerp.web.search.Widget.make_id` has been removed
244
245 * Search field objects are not openerp widgets anymore, their
246   ``start`` is not generally called
247
248 * :js:func:`~openerp.web.search.Input.clear` has been removed since
249   clearing the search view now simply consists of removing all search
250   facets from VisualSearch
251
252 * :js:func:`~openerp.web.search.Input.get_domain` and
253   :js:func:`~openerp.web.search.Input.get_context` now take a
254   :js:class:`~VS.model.SearchFacet` as parameter, from which it's
255   their job to get whatever value they want
256
257 * :js:func:`~openerp.web.search.Input.get_groupby` has been added. It returns
258   an :js:class:`Array` of context-like constructs. By default, it does not do
259   anything in :js:class:`~openerp.web.search.Field` and it returns the various
260   contexts of its enabled filters in
261   :js:class:`~openerp.web.search.FilterGroup`.
262
263 Filters
264 +++++++
265
266 * :js:func:`openerp.web.search.Filter.is_enabled` has been removed
267
268 * :js:class:`~openerp.web.search.FilterGroup` instances are still
269   rendered (and started) in the "advanced search" drawer.
270
271 Fields
272 ++++++
273
274 * ``get_value`` now takes a :js:class:`~VS.model.SearchFacet` (instead
275   of taking no argument).
276
277   A default implementation is provided as
278   :js:func:`openerp.web.search.Field.get_value` and simply calls
279   :js:func:`VS.model.SearchFacet.value`.
280
281 * The third argument to
282   :js:func:`~openerp.web.search.Field.make_domain` is now the
283   :js:class:`~VS.model.SearchFacet` received by
284   :js:func:`~openerp.web.search.Field.get_domain`, so child classes
285   have all the information they need to derive the "right" resulting
286   domain.
287
288 Custom filters
289 ++++++++++++++
290
291 Instead of being an intrinsic part of the search view, custom filters
292 are now a special case of filter groups. They are treated specially
293 still, but much less so than they used to be.
294
295 Many To One
296 +++++++++++
297
298 * Because the autocompletion service is now provided by the search
299   view itself,
300   :js:func:`openerp.web.search.ManyToOneField.setup_autocomplete` has
301   been removed.
302
303 .. [#] the library code is untouched, all patching is performed in the
304        Search view's implementation module. Changes to the
305        VisualSearch code should only update the library to new
306        revisions or releases.
307 .. [#] search view fields may also bundle context data to add to the
308        search context
309
310 .. _commit 3fca87101d:
311      https://github.com/documentcloud/visualsearch/commit/3fca87101d