[TYPO] Set the right category for the Point Of Sale
[odoo/odoo.git] / doc / widget.rst
1 User Interaction: Widget
2 ========================
3
4 This is the base class for all visual components. It corresponds to an MVC
5 view. It provides a number of services to handle a section of a page:
6
7 * Rendering with QWeb
8
9 * Parenting-child relations
10
11 * Life-cycle management (including facilitating children destruction when a
12   parent object is removed)
13
14 * DOM insertion, via jQuery-powered insertion methods. Insertion targets can
15   be anything the corresponding jQuery method accepts (generally selectors,
16   DOM nodes and jQuery objects):
17
18   :js:func:`~openerp.base.Widget.appendTo`
19     Renders the widget and inserts it as the last child of the target, uses
20     `.appendTo()`_
21
22   :js:func:`~openerp.base.Widget.prependTo`
23     Renders the widget and inserts it as the first child of the target, uses
24     `.prependTo()`_
25
26   :js:func:`~openerp.base.Widget.insertAfter`
27     Renders the widget and inserts it as the preceding sibling of the target,
28     uses `.insertAfter()`_
29
30   :js:func:`~openerp.base.Widget.insertBefore`
31     Renders the widget and inserts it as the following sibling of the target,
32     uses `.insertBefore()`_
33
34 * Backbone-compatible shortcuts
35
36 DOM Root
37 --------
38
39 A :js:class:`~openerp.web.Widget` is responsible for a section of the
40 page materialized by the DOM root of the widget. The DOM root is
41 available via the :js:attr:`~openerp.web.Widget.el` and
42 :js:attr:`~openerp.web.Widget.$element` attributes, which are
43 respectively the raw DOM Element and the jQuery wrapper around the DOM
44 element.
45
46 There are two main ways to define and generate this DOM root:
47
48 .. js:attribute:: openerp.web.Widget.template
49
50     Should be set to the name of a QWeb template (a
51     :js:class:`String`). If set, the template will be rendered after
52     the widget has been initialized but before it has been
53     started. The root element generated by the template will be set as
54     the DOM root of the widget.
55
56 .. js:attribute:: openerp.web.Widget.tagName
57
58     Used if the widget has no template defined. Defaults to ``div``,
59     will be used as the tag name to create the DOM element to set as
60     the widget's DOM root. It is possible to further customize this
61     generated DOM root with the following attributes:
62
63     .. js:attribute:: openerp.web.Widget.id
64
65         Used to generate an ``id`` attribute on the generated DOM
66         root.
67
68     .. js:attribute:: openerp.web.Widget.className
69
70         Used to generate a ``class`` attribute on the generated DOM root.
71
72     .. js:attribute:: openerp.web.Widget.attributes
73
74         Mapping (object literal) of attribute names to attribute
75         values. Each of these k:v pairs will be set as a DOM attribute
76         on the generated DOM root.
77
78     None of these is used in case a template is specified on the widget.
79
80 The DOM root can also be defined programmatically by overridding
81
82 .. js:function:: openerp.web.Widget.renderElement
83
84     Renders the widget's DOM root and sets it. The default
85     implementation will render a set template or generate an element
86     as described above, and will call
87     :js:func:`~openerp.web.Widget.setElement` on the result.
88
89     Any override to :js:func:`~openerp.web.Widget.renderElement` which
90     does not call its ``_super`` **must** call
91     :js:func:`~openerp.web.Widget.setElement` with whatever it
92     generated or the widget's behavior is undefined.r
93
94     .. note::
95
96         The default :js:func:`~openerp.web.Widget.renderElement` can
97         be called repeatedly, it will *replace* the previous DOM root
98         (using ``replaceWith``). However, this requires that the
99         widget correctly sets and unsets its events (and children
100         widgets). Generally,
101         :js:func:`~openerp.web.Widget.renderElement` should not be
102         called repeatedly unless the widget advertizes this feature.
103
104 Accessing DOM content
105 ~~~~~~~~~~~~~~~~~~~~~
106
107 Because a widget is only responsible for the content below its DOM
108 root, there is a shortcut for selecting sub-sections of a widget's
109 DOM:
110
111 .. js:function:: openerp.web.Widget.$(selector)
112
113     Applies the CSS selector specified as parameter to the widget's
114     DOM root.
115
116     .. code-block:: javascript
117
118         this.$(selector);
119
120     is functionally identical to:
121
122     .. code-block:: javascript
123
124         this.$element.find(selector);
125
126     :param String selector: CSS selector
127     :returns: jQuery object
128
129     .. note:: this helper method is compatible with
130               ``Backbone.View.$``
131
132 Resetting the DOM root
133 ~~~~~~~~~~~~~~~~~~~~~~
134
135 .. js:function:: openerp.web.Widget.setElement(element)
136
137     Re-sets the widget's DOM root to the provided element, also
138     handles re-setting the various aliases of the DOM root as well as
139     unsetting and re-setting delegated events.
140
141     :param Element element: a DOM element or jQuery object to set as
142                             the widget's DOM root
143
144     .. note:: should be mostly compatible with `Backbone's
145               setElement`_
146
147 DOM events handling
148 -------------------
149
150 A widget will generally need to respond to user action within its
151 section of the page. This entails binding events to DOM elements.
152
153 To this end, :js:class:`~openerp.web.Widget` provides an shortcut:
154
155 .. js:attribute:: openerp.web.Widget.events
156
157     Events are a mapping of ``event selector`` (an event name and a
158     CSS selector separated by a space) to a callback. The callback can
159     be either a method name in the widget or a function. In either
160     case, the ``this`` will be set to the widget.
161
162     The selector is used for jQuery's `event delegation`_, the
163     callback will only be triggered for descendants of the DOM root
164     matching the selector [0]_. If the selector is left out (only an
165     event name is specified), the event will be set directly on the
166     widget's DOM root.
167
168 .. js:function:: openerp.web.Widget.delegateEvents
169
170     This method is in charge of binding
171     :js:attr:`~openerp.web.Widget.events` to the DOM. It is
172     automatically called after setting the widget's DOM root.
173
174     It can be overridden to set up more complex events than the
175     :js:attr:`~openerp.web.Widget.events` map allows, but the parent
176     should always be called (or :js:attr:`~openerp.web.Widget.events`
177     won't be handled correctly).
178
179 .. js:function:: openerp.web.Widget.undelegateEvents
180
181     This method is in charge of unbinding
182     :js:attr:`~openerp.web.Widget.events` from the DOM root when the
183     widget is destroyed or the DOM root is reset, in order to avoid
184     leaving "phantom" events.
185
186     It should be overridden to un-set any event set in an override of
187     :js:func:`~openerp.web.Widget.delegateEvents`.
188
189 .. note:: this behavior should be compatible with `Backbone's
190           delegateEvents`_, apart from not accepting any argument.
191
192 Subclassing Widget
193 ------------------
194
195 :js:class:`~openerp.base.Widget` is subclassed in the standard manner (via the
196 :js:func:`~openerp.base.Class.extend` method), and provides a number of
197 abstract properties and concrete methods (which you may or may not want to
198 override). Creating a subclass looks like this:
199
200 .. code-block:: javascript
201
202     var MyWidget = openerp.base.Widget.extend({
203         // QWeb template to use when rendering the object
204         template: "MyQWebTemplate",
205
206         init: function(parent) {
207             this._super(parent);
208             // insert code to execute before rendering, for object
209             // initialization
210         },
211         start: function() {
212             this._super();
213             // post-rendering initialization code, at this point
214             // ``this.$element`` has been initialized
215             this.$element.find(".my_button").click(/* an example of event binding * /);
216
217             // if ``start`` is asynchronous, return a promise object so callers
218             // know when the object is done initializing
219             return this.rpc(/* … */)
220         }
221     });
222
223 The new class can then be used in the following manner:
224
225 .. code-block:: javascript
226
227     // Create the instance
228     var my_widget = new MyWidget(this);
229     // Render and insert into DOM
230     my_widget.appendTo(".some-div");
231
232 After these two lines have executed (and any promise returned by ``appendTo``
233 has been resolved if needed), the widget is ready to be used.
234
235 .. note:: the insertion methods will start the widget themselves, and will
236           return the result of :js:func:`~openerp.base.Widget.start()`.
237
238           If for some reason you do not want to call these methods, you will
239           have to first call :js:func:`~openerp.base.Widget.render()` on the
240           widget, then insert it into your DOM and start it.
241
242 If the widget is not needed anymore (because it's transient), simply terminate
243 it:
244
245 .. code-block:: javascript
246
247     my_widget.destroy();
248
249 will unbind all DOM events, remove the widget's content from the DOM and
250 destroy all widget data.
251
252 .. [0] not all DOM events are compatible with events delegation
253
254 .. _.appendTo():
255     http://api.jquery.com/appendTo/
256
257 .. _.prependTo():
258     http://api.jquery.com/prependTo/
259
260 .. _.insertAfter():
261     http://api.jquery.com/insertAfter/
262
263 .. _.insertBefore():
264     http://api.jquery.com/insertBefore/
265
266 .. _event delegation:
267     http://api.jquery.com/delegate/
268
269 .. _Backbone's setElement:
270     http://backbonejs.org/#View-setElement
271
272 .. _Backbone's delegateEvents:
273     http://backbonejs.org/#View-delegateEvents
274