1Guidelines and Recommendations
2==============================
3
4Web Module Recommendations
5--------------------------
6
7Identifiers (``id`` attribute) should be avoided
8''''''''''''''''''''''''''''''''''''''''''''''''
9
10In generic applications and modules, ``@id`` limits the reusabily of
11components and tends to make code more brittle.
12
13Just about all the time, they can be replaced with nothing, with
14classes or with keeping a reference to a DOM node or a jQuery element
15around.
16
17.. note::
18
19    If it is *absolutely necessary* to have an ``@id`` (because a
20    third-party library requires one and can't take a DOM element), it
21    should be generated with `_.uniqueId
22    <http://underscorejs.org/#uniqueId>`_ or some other similar
23    method.
24
25Avoid predictable/common CSS class names
26''''''''''''''''''''''''''''''''''''''''
27
28Class names such as "content" or "navigation" might match the desired
29meaning/semantics, but it is likely an other developer will have the
30same need, creating a naming conflict and unintended behavior. Generic
31class names should be prefixed with e.g. the name of the component
32they belong to (creating "informal" namespaces, much as in C or
33Objective-C)
34
35Global selectors should be avoided
36''''''''''''''''''''''''''''''''''
37
38Because a component may be used several times in a single page (an
39example in OpenERP is dashboards), queries should be restricted to a
40given component's scope. Unfiltered selections such as ``$(selector)``
41or ``document.querySelectorAll(selector)`` will generally lead to
42unintended or incorrect behavior.
43
44OpenERP Web's :js:class:`~openerp.web.Widget` has an attribute
45providing its DOM root :js:attr:`Widget.$el <openerp.web.Widget.$el>`,
46and a shortcut to select nodes directly :js:attr:`Widget.$
47<openerp.web.Widget.$>`.
48
49More generally, never assume your components own or controls anything
50beyond its own personal DOM.
51
52Understand deferreds
53''''''''''''''''''''
54
55Deferreds, promises, futures, …
56
57Known under many names, these objects are essential to and (in OpenERP
58Web) widely used for making :doc:`asynchronous javascript operations
59<async>` palatable and understandable.
60
61OpenERP Web guidelines
62----------------------
63
64* HTML templating/rendering should use :doc:`qweb` unless absolutely
65  trivial.
66
67* All interactive components (components displaying information to the
68  screen or intercepting DOM events) must inherit from
69  :class:`~openerp.web.Widget` and correctly implement and use its API
70  and lifecycle.
71
72* All css classes must be prefixed with *oe_* .
73
74* Asynchronous functions (functions which call :ref:`session.rpc
75  <rpc_rpc>` directly or indirectly at the very least) *must* return
76  deferreds, so that callers of overriders can correctly synchronize
77  with them.
78
79New Javascript guidelines
80-------------------------
81
82From v11, we introduce a new coding standard for Odoo Javascript code.  Here it
83is:
84
85* add "use strict"; on top of every odoo JS module
86
87* name all entities exported by a JS module. So, instead of
88
89  .. code-block:: javascript
90
91      return Widget.extend({
92        ...
93      });
94
95you should use:
96
97  .. code-block:: javascript
98
99      var MyWidget = Widget.extend({
100        ...
101      });
102
103      return MyWidget
104
105* there should be one space between function and the left parenthesis:
106
107  .. code-block:: javascript
108
109    function (a, b) {}
110
111* JS files should have a (soft) limit of 80 chars width, and a hard limit of 100
112
113* document every functions and every files, with the style JSDoc.
114
115* for function overriding other functions, consider adding the tag @override in
116  the JS Doc.  Also, you can mention which method is overridden:
117
118  .. code-block:: javascript
119
120    /**
121     * When a save operation has been confirmed from the model, this method is
122     * called.
123     *
124     * @override method from field manager mixin
125     * @param {string} id
126     * @returns {Deferred}
127     */
128    _confirmSave: function (id) {
129
130* there should be an empty line between the main function comments and the tags,
131  or parameter descriptions
132
133* avoid introspection: don't build dynamically a method name and call it.  It is
134  more fragile and more difficult to refactor
135
136* methods should be private if possible
137
138* never read an attribute of an attribute on somethig that you have a reference.
139  So, this is not good:
140
141  .. code-block:: javascript
142
143    this.myObject.propA.propB
144
145* never use a reference to the parent widget
146
147* avoid using the 'include' functionality: extending a class is fine and does
148  not cause issue, including a class is much more fragile, and may not work.
149
150* For the widgets, here is how the various attributes/functions should be
151  ordered:
152
153  1. all static attributes, such as template, events, custom_events, ...
154
155  2. all methods from the lifecycle of a widget, in this order: init, willStart,
156     start, destroy
157
158  3. If there are public methods, a section titled "Public", with an empty line
159    before and after
160
161  4. all public methods, camelcased, in alphabetic order
162
163  5. If there are private methods, a section titled "Private", with an empty line
164    before and after
165
166  6. all private methods, camelcased and prefixed with _, in alphabetic order
167
168  7. If there are event handlers, a section titled "Handlers", with an empty line
169    before and after
170
171  8. all handlers, camelcased and prefixed with _on, in alphabetic order
172
173  9. If there are static methods, they should be in a section titled "Static".
174     All static methods are considered public, camelcased with no _.
175
176* write unit tests
177
178* for the event handlers defined by the key 'event' or 'custom_events', don't
179  inline the function.  Always add a string name, and add the definition in the
180  handler section
181
182* one space after if and for
183
184* never call private methods on another object
185
186* object definition on more than one line: each element should have a trailing
187  comma.
188
189* strings: double quotes for all textual strings (such as "Hello"), and single
190  quotes for all other strings, such as a css selector '.o_form_view'
191
192* always use this._super.apply(this, arguments);
193
194* keys in an object: ordered by alphabetic order