1 User Interaction: Widget
2 ========================
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:
9 * Parenting-child relations
11 * Life-cycle management (including facilitating children destruction when a
12 parent object is removed)
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):
18 :js:func:`~openerp.base.Widget.appendTo`
19 Renders the widget and inserts it as the last child of the target, uses
22 :js:func:`~openerp.base.Widget.prependTo`
23 Renders the widget and inserts it as the first child of the target, uses
26 :js:func:`~openerp.base.Widget.insertAfter`
27 Renders the widget and inserts it as the preceding sibling of the target,
28 uses `.insertAfter()`_
30 :js:func:`~openerp.base.Widget.insertBefore`
31 Renders the widget and inserts it as the following sibling of the target,
32 uses `.insertBefore()`_
34 * Backbone-compatible shortcuts
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
46 There are two main ways to define and generate this DOM root:
48 .. js:attribute:: openerp.web.Widget.template
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.
56 .. js:attribute:: openerp.web.Widget.tagName
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:
63 .. js:attribute:: openerp.web.Widget.id
65 Used to generate an ``id`` attribute on the generated DOM
68 .. js:attribute:: openerp.web.Widget.className
70 Used to generate a ``class`` attribute on the generated DOM root.
72 .. js:attribute:: openerp.web.Widget.attributes
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.
78 None of these is used in case a template is specified on the widget.
80 The DOM root can also be defined programmatically by overridding
82 .. js:function:: openerp.web.Widget.renderElement
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.
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
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
101 :js:func:`~openerp.web.Widget.renderElement` should not be
102 called repeatedly unless the widget advertizes this feature.
104 Accessing DOM content
105 ~~~~~~~~~~~~~~~~~~~~~
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
111 .. js:function:: openerp.web.Widget.$(selector)
113 Applies the CSS selector specified as parameter to the widget's
116 .. code-block:: javascript
120 is functionally identical to:
122 .. code-block:: javascript
124 this.$element.find(selector);
126 :param String selector: CSS selector
127 :returns: jQuery object
129 .. note:: this helper method is compatible with
132 Resetting the DOM root
133 ~~~~~~~~~~~~~~~~~~~~~~
135 .. js:function:: openerp.web.Widget.setElement(element)
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.
141 :param Element element: a DOM element or jQuery object to set as
142 the widget's DOM root
144 .. note:: should be mostly compatible with `Backbone's
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.
153 To this end, :js:class:`~openerp.web.Widget` provides an shortcut:
155 .. js:attribute:: openerp.web.Widget.events
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.
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
168 .. js:function:: openerp.web.Widget.delegateEvents
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.
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).
179 .. js:function:: openerp.web.Widget.undelegateEvents
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.
186 It should be overridden to un-set any event set in an override of
187 :js:func:`~openerp.web.Widget.delegateEvents`.
189 .. note:: this behavior should be compatible with `Backbone's
190 delegateEvents`_, apart from not accepting any argument.
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:
200 .. code-block:: javascript
202 var MyWidget = openerp.base.Widget.extend({
203 // QWeb template to use when rendering the object
204 template: "MyQWebTemplate",
206 init: function(parent) {
208 // insert code to execute before rendering, for object
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 * /);
217 // if ``start`` is asynchronous, return a promise object so callers
218 // know when the object is done initializing
219 return this.rpc(/* … */)
223 The new class can then be used in the following manner:
225 .. code-block:: javascript
227 // Create the instance
228 var my_widget = new MyWidget(this);
229 // Render and insert into DOM
230 my_widget.appendTo(".some-div");
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.
235 .. note:: the insertion methods will start the widget themselves, and will
236 return the result of :js:func:`~openerp.base.Widget.start()`.
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.
242 If the widget is not needed anymore (because it's transient), simply terminate
245 .. code-block:: javascript
249 will unbind all DOM events, remove the widget's content from the DOM and
250 destroy all widget data.
252 .. [0] not all DOM events are compatible with events delegation
255 http://api.jquery.com/appendTo/
258 http://api.jquery.com/prependTo/
261 http://api.jquery.com/insertAfter/
264 http://api.jquery.com/insertBefore/
266 .. _event delegation:
267 http://api.jquery.com/delegate/
269 .. _Backbone's setElement:
270 http://backbonejs.org/#View-setElement
272 .. _Backbone's delegateEvents:
273 http://backbonejs.org/#View-delegateEvents