From d6074e66195065581a002f865df76d192fbc8ab1 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 12 Aug 2011 12:36:43 +0200 Subject: [PATCH] [IMP] move openerp.base.Widget to relevant section of the actual dogs (as a guide), remove old manual openerp.base.Widget APIDoc bzr revid: xmo@openerp.com-20110812103643-2ew32jiqdsm71jqe --- addons/base/controllers/main.py | 8 +- addons/base/static/src/js/core.js | 53 ------ doc/source/addons.rst | 291 +++++++++++------------------- doc/source/development.rst | 12 +- 4 files changed, 115 insertions(+), 249 deletions(-) diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 4f6b3ea4f70..36db03d6bba 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -772,8 +772,8 @@ class View(openerpweb.Controller): """ Parses an arbitrary string containing a domain, transforms it to either a literal domain or a :class:`openerpweb.nonliterals.Domain` - :param domain: the domain to parse, if the domain is not a string it is assumed to - be a literal domain and is returned as-is + :param domain: the domain to parse, if the domain is not a string it + is assumed to be a literal domain and is returned as-is :param session: Current OpenERP session :type session: openerpweb.openerpweb.OpenERPSession """ @@ -789,8 +789,8 @@ class View(openerpweb.Controller): """ Parses an arbitrary string containing a context, transforms it to either a literal context or a :class:`openerpweb.nonliterals.Context` - :param context: the context to parse, if the context is not a string it is assumed to - be a literal domain and is returned as-is + :param context: the context to parse, if the context is not a string it + is assumed to be a literal domain and is returned as-is :param session: Current OpenERP session :type session: openerpweb.openerpweb.OpenERPSession """ diff --git a/addons/base/static/src/js/core.js b/addons/base/static/src/js/core.js index 859c96645a1..da9b5abf3e8 100644 --- a/addons/base/static/src/js/core.js +++ b/addons/base/static/src/js/core.js @@ -373,59 +373,6 @@ openerp.base.SessionAware = openerp.base.Class.extend({ } }); -/** - * Base class for all visual components. Provides a lot of functionalities helpful - * for the management of a part of the DOM. - * - * Widget handles: - * - Rendering with QWeb. - * - Life-cycle management and parenting (when a parent is destroyed, all its children are - * destroyed too). - * - Insertion in DOM. - * - * Widget also extends SessionAware for ease of use. - * - * Guide to create implementations of the Widget class: - * ============================================== - * - * Here is a sample child class: - * - * MyWidget = openerp.base.Widget.extend({ - * // the name of the QWeb template to use for rendering - * template: "MyQWebTemplate", - * // identifier prefix, it is useful to put an obvious one for debugging - * identifier_prefix: 'my-id-prefix-', - * - * init: function(parent) { - * this._super(parent); - * // stuff that you want to init before the rendering - * }, - * start: function() { - * this._super(); - * // stuff you want to make after the rendering, `this.$element` holds a correct value - * this.$element.find(".my_button").click(/* an example of event binding * /); - * - * // if you have some asynchronous operations, it's a good idea to return - * // a promise in start() - * var promise = this.rpc(...); - * return promise; - * } - * }); - * - * Now this class can simply be used with the following syntax: - * - * var my_widget = new MyWidget(this); - * my_widget.appendTo($(".some-div")); - * - * With these two lines, the MyWidget instance was inited, rendered, it was inserted into the - * DOM inside the ".some-div" div and its events were binded. - * - * And of course, when you don't need that widget anymore, just do: - * - * my_widget.stop(); - * - * That will kill the widget in a clean way and erase its content from the dom. - */ openerp.base.Widget = openerp.base.SessionAware.extend({ /** * The name of the QWeb template that will be used for rendering. Must be diff --git a/doc/source/addons.rst b/doc/source/addons.rst index 4f371192760..7261e57ebd3 100644 --- a/doc/source/addons.rst +++ b/doc/source/addons.rst @@ -113,6 +113,98 @@ initializing the addon. Creating new standard roles --------------------------- +Widget +++++++ + +This is the base class for all visual components. It provides a number of +services for the management of a DOM subtree: + +* Rendering with QWeb + +* Parenting-child relations + +* Life-cycle management (including facilitating children destruction when a + parent object is removed) + +* DOM insertion, via jQuery-powered insertion methods. Insertion targets can + be anything the corresponding jQuery method accepts (generally selectors, + DOM nodes and jQuery objects): + + :js:func:`~openerp.base.Widget.appendTo` + Renders the widget and inserts it as the last child of the target, uses + `.appendTo()`_ + + :js:func:`~openerp.base.Widget.prependTo` + Renders the widget and inserts it as the first child of the target, uses + `.prependTo()`_ + + :js:func:`~openerp.base.Widget.insertAfter` + Renders the widget and inserts it as the preceding sibling of the target, + uses `.insertAfter()`_ + + :js:func:`~openerp.base.Widget.insertBefore` + Renders the widget and inserts it as the following sibling of the target, + uses `.insertBefore()`_ + +:js:class:`~openerp.base.Widget` inherits from +:js:class:`~openerp.base.SessionAware`, so subclasses can easily access the +RPC layers. + +Subclassing Widget +~~~~~~~~~~~~~~~~~~ + +:js:class:`~openerp.base.Widget` is subclassed in the standard manner (via the +:js:func:`~openerp.base.Class.extend` method), and provides a number of +abstract properties and concrete methods (which you may or may not want to +override). Creating a subclass looks like this: + +.. code-block:: javascript + + var MyWidget = openerp.base.Widget.extend({ + // QWeb template to use when rendering the object + template: "MyQWebTemplate", + // autogenerated id prefix, specificity helps when debugging + identifier_prefix: 'my-id-prefix-', + + init: function(parent) { + this._super(parent); + // insert code to execute before rendering, for object + // initialization + }, + start: function() { + this._super(); + // post-rendering initialization code, at this point + // ``this.$element`` has been initialized + this.$element.find(".my_button").click(/* an example of event binding * /); + + // if ``start`` is asynchronous, return a promise object so callers + // know when the object is done initializing + return this.rpc(/* … */) + } + }); + +The new class can then be used in the following manner: + +.. code-block:: javascript + + // Create the instance + var my_widget = new MyWidget(this); + // Render and insert into DOM + my_widget.appendTo(".some-div"); + +After these two lines have executed (and any promise returned by ``appendTo`` +has been resolved if needed), the widget is ready to be used. + +If the widget is not needed anymore (because it's transient), simply terminate +it: + +.. code-block:: javascript + + my_widget.stop(); + +will unbind all DOM events, remove the widget's content from the DOM and +destroy all widget data. + Views +++++ @@ -236,193 +328,6 @@ replace ``addons`` by the directory in which your own addon lives. and run ``nosetests addons`` instead of the ``unit2`` command, the result should be exactly the same. -APIs ----- - -Javascript -++++++++++ - -.. js:class:: openerp.base.Widget(view, node) - - :param openerp.base.Controller view: The view to which the widget belongs - :param Object node: the ``fields_view_get`` descriptor for the widget - - .. js:attribute:: $element - - The widget's root element as jQuery object - -.. js:class:: openerp.base.DataSet(session, model) - - :param openerp.base.Session session: the RPC session object - :param String model: the model managed by this dataset - - The DataSet is the abstraction for a sequence of records stored in - database. - - It provides interfaces for reading records based on search - criteria, and for selecting and fetching records based on - activated ids. - - .. js:function:: fetch([offset][, limit]) - - :param Number offset: the index from which records should start - being returned (section) - :param Number limit: the maximum number of records to return - :returns: the dataset instance it was called on - - Asynchronously fetches the records selected by the DataSet's - domain and context, in the provided sort order if any. - - Only fetches the fields selected by the DataSet. - - On success, triggers :js:func:`on_fetch` - - .. js:function:: on_fetch(records, event) - - :param Array records: an array of - :js:class:`openerp.base.DataRecord` - matching the DataSet's selection - :param event: a data holder letting the event handler fetch - meta-informations about the event. - :type event: OnFetchEvent - - Fired after :js:func:`fetch` is done fetching the records - selected by the DataSet. - - .. js:function:: active_ids - - :returns: the dataset instance it was called on - - Asynchronously fetches the active records for this DataSet. - - On success, triggers :js:func:`on_active_ids` - - .. js:function:: on_active_ids(records) - - :param Array records: an array of - :js:class:`openerp.base.DataRecord` - matching the currently active ids - - Fired after :js:func:`active_ids` fetched the records matching - the DataSet's active ids. - - .. js:function:: active_id - - :returns: the dataset instance in was called on - - Asynchronously fetches the current active record. - - On success, triggers :js:func:`on_active_id` - - .. js:function:: on_active_id(record) - - :param Object record: the record fetched by - :js:func:`active_id`, or ``null`` - :type record: openerp.base.DataRecord - - Fired after :js:func:`active_id` fetched the record matching - the dataset's active id - - .. js:function:: set(options) - - :param Object options: the options to set on the dataset - :type options: DataSetOptions - :returns: the dataset instance it was called on - - Configures the data set by setting various properties on it - - .. js:function:: prev - - :returns: the dataset instance it was called on - - Activates the id preceding the current one in the active ids - sequence of the dataset. - - If the current active id is at the start of the sequence, - wraps back to the last id of the sequence. - - .. js:function:: next - - :returns: the dataset instance it was called on - - Activates the id following the current one in the active ids - sequence. - - If the current active id is the last of the sequence, wraps - back to the beginning of the active ids sequence. - - .. js:function:: select(ids) - - :param Array ids: the identifiers to activate on the dataset - :returns: the dataset instance it was called on - - Activates all the ids specified in the dataset, resets the - current active id to be the first id of the new sequence. - - The internal order will be the same as the ids list provided. - - .. js:function:: get_active_ids - - :returns: the list of current active ids for the dataset - - .. js:function:: activate(id) - - :param Number id: the id to activate - :returns: the dataset instance it was called on - - Activates the id provided in the dataset. If no ids are - selected, selects the id in the dataset. - - If ids are already selected and the provided id is not in that - selection, raises an error. - - .. js:function:: get_active_id - - :returns: the dataset's current active id - -Ad-hoc objects and structural types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -These objects are not associated with any specific class, they're -generally literal objects created on the spot. Names are merely -convenient ways to refer to them and their properties. - -.. js:class:: OnFetchEvent - - .. js:attribute:: context - - The context used for the :js:func:`fetch` call (domain set on - the :js:class:`openerp.base.DataSet` when ``fetch`` was - called) - - .. js:attribute:: domain - - The domain used for the :js:func:`fetch` call - - .. js:attribute:: limit - - The limit with which the original :js:func:`fetch` call was - performed - - .. js:attribute:: offset - - The offset with which the original :js:func:`fetch` call was - performed - - .. js:attribute:: sort - - The sorting criteria active on the - :js:class:`openerp.base.DataSet` when :js:func:`fetch` was - called - -.. js:class:: DataSetOptions - - .. js:attribute:: context - - .. js:attribute:: domain - - .. js:attribute:: sort - Python ++++++ @@ -499,3 +404,15 @@ Python .. _promise object: http://api.jquery.com/deferred.promise/ + +.. _.appendTo(): + http://api.jquery.com/appendTo/ + +.. _.prependTo(): + http://api.jquery.com/prependTo/ + +.. _.insertAfter(): + http://api.jquery.com/insertAfter/ + +.. _.insertBefore(): + http://api.jquery.com/insertBefore/ diff --git a/doc/source/development.rst b/doc/source/development.rst index bfb176cb5c5..85fbebcceb3 100644 --- a/doc/source/development.rst +++ b/doc/source/development.rst @@ -374,11 +374,13 @@ Deletion can be overridden by replacing the calls :js:func:`~openerp.base.DataSet.unlink` in order to remove the records entirely. -.. note:: the list-wise deletion button (next to the record addition button) - simply proxies to :js:func:`~openerp.base.ListView.do_delete` after - obtaining all selected record ids, but it is possible to override it - alone by replacing - :js:func:`~openerp.base.ListView.do_delete_selected`. +.. note:: + + the list-wise deletion button (next to the record addition button) + simply proxies to :js:func:`~openerp.base.ListView.do_delete` after + obtaining all selected record ids, but it is possible to override it + alone by replacing + :js:func:`~openerp.base.ListView.do_delete_selected`. Internal API Doc ----------------