From 556d06c65ba0786afbc97732a4bcc8e00b3af082 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Wed, 27 Jul 2011 21:52:21 +0200 Subject: [ADD] niv-style controller/widget skeleton bzr revid: al@openerp.com-20110727195221-gy6u9e4xw0sflh4c --- addons/base/static/src/js/controller.js | 301 ++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) (limited to 'addons/base/static/src/js/controller.js') diff --git a/addons/base/static/src/js/controller.js b/addons/base/static/src/js/controller.js index c9ca3193e70..1a13ab18607 100644 --- a/addons/base/static/src/js/controller.js +++ b/addons/base/static/src/js/controller.js @@ -145,6 +145,10 @@ instance.base.generate_null_object_class = function(claz, add) { return tmpclass.extend(add || {}); }; +// -------------------------------------------------------- +// OLD +// -------------------------------------------------------- + /** * OpenERP Controller * TODO merge BaseWidget with Controller @@ -243,6 +247,303 @@ instance.base.Controller = instance.base.Class.extend( /** @lends instance.base. } }); +/** + * OpenERP session aware controller + * a controller takes an already existing dom element and manage it + */ +instance.base.Controller = instance.base.Controller.extend( /** @lends openerp.base.Controller# */{ + init: function(parent, element_id) { + this._super(parent, element_id); + if(this.controller_parent && this.controller_parent.session) { + this.session = this.controller_parent.session; + } + }, + /** + * Performs a JSON-RPC call + * + * @param {String} url endpoint url + * @param {Object} data RPC parameters + * @param {Function} success RPC call success callback + * @param {Function} error RPC call error callback + * @returns {jQuery.Deferred} deferred object for the RPC call + */ + rpc: function(url, data, success, error) { + return this.session.rpc(url, data, success, error); + }, + do_action: function(action, on_finished) { + return this.parent.do_action(action, on_finished); + } +}); + +/** + * OpenERP session aware widget + * A widget is a controller that doesnt take an element_id + * it render its own html render() that you should insert into the dom + * and bind it at start() + */ +instance.base.BaseWidget = instance.base.Controller.extend({ + /** + * The name of the QWeb template that will be used for rendering. Must be + * redefined in subclasses or the render() method can not be used. + * + * @type string + */ + template: null, + /** + * The prefix used to generate an id automatically. Should be redefined in + * subclasses. If it is not defined, a default identifier will be used. + * + * @type string + */ + identifier_prefix: 'generic-identifier', + /** + * Base class for widgets. Handle rendering (based on a QWeb template), + * identifier generation, parenting and destruction of the widget. + * Also initialize the identifier. + * + * @constructs + * @params {openerp.base.search.BaseWidget} parent The parent widget. + */ + init: function (parent) { + this._super(parent); + this.make_id(this.identifier_prefix); + }, + /** + * Sets and returns a globally unique identifier for the widget. + * + * If a prefix is appended, the identifier will be appended to it. + * + * @params sections prefix sections, empty/falsy sections will be removed + */ + make_id: function () { + this.element_id = _.uniqueId(_.toArray(arguments).join('_')); + return this.element_id; + }, + /** + * Render the widget. This.template must be defined. + * The content of the current object is passed as context to the template. + * + * @param {object} additional Additional context arguments to pass to the template. + */ + render: function (additional) { + return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {})); + }, + /** + * "Starts" the widgets. Called at the end of the rendering, this allows + * to get a jQuery object referring to the DOM ($element attribute). + */ + start: function () { + this._super(); + var tmp = document.getElementById(this.element_id); + this.$element = tmp ? $(tmp) : null; + }, + /** + * "Stops" the widgets. Called when the view destroys itself, this + * lets the widgets clean up after themselves. + */ + stop: function () { + if(this.$element != null) { + this.$element.remove(); + } + this._super(); + } +}); + +// -------------------------------------------------------- +// N-style aka New-Style or Niv-Style +// -------------------------------------------------------- + +instance.base.NivController = instance.base.Class.extend({ + init: function(parent) { + this.controller_parent = parent; + // Take the session of the parent if defined + if(this.controller_parent && this.controller_parent.session) { + this.session = this.controller_parent.session; + } + // Transform on_* method into openerp.base.callbacks + for (var name in this) { + if(typeof(this[name]) == "function") { + this[name].debug_name = name; + // bind ALL function to this not only on_and _do ? + if((/^on_|^do_/).test(name)) { + this[name] = instance.base.callback(this, this[name]); + } + } + } + }, + /** + * Event binding, rpc and callback calling required to initialize the + * object should happen here + * + * Returns a promise object letting callers (subclasses and direct callers) + * know when this component is done starting + * + * @returns {jQuery.Deferred} + */ + start: function() { + // returns an already fulfilled promise. Maybe we could return nothing? + // $.when can take non-deferred and in that case it simply considers + // them all as fulfilled promises. + // But in thise case we *have* to ensure callers use $.when and don't + // try to call deferred methods on this return value. + return $.Deferred().done().promise(); + }, + stop: function() { + }, + log: function() { + var args = Array.prototype.slice.call(arguments); + var caller = arguments.callee.caller; + // TODO add support for line number using + // https://github.com/emwendelin/javascript-stacktrace/blob/master/stacktrace.js + // args.unshift("" + caller.debug_name); + this.on_log.apply(this,args); + }, + on_log: function() { + if(window.openerp.debug || (window.location.search.indexOf('?debug') !== -1)) { + var notify = false; + var body = false; + if(window.console) { + console.log(arguments); + } else { + body = true; + } + var a = Array.prototype.slice.call(arguments, 0); + for(var i = 0; i < a.length; i++) { + var v = a[i]==null ? "null" : a[i].toString(); + if(i==0) { + notify = v.match(/^not/); + body = v.match(/^bod/); + } + if(body) { + $('
').text(v).appendTo($('body'));
+                }
+                if(notify && this.notification) {
+                    this.notification.notify("Logging:",v);
+                }
+            }
+        }
+
+    },
+    /**
+     * Performs a JSON-RPC call
+     *
+     * @param {String} url endpoint url
+     * @param {Object} data RPC parameters
+     * @param {Function} success RPC call success callback
+     * @param {Function} error RPC call error callback
+     * @returns {jQuery.Deferred} deferred object for the RPC call
+     */
+    rpc: function(url, data, success, error) {
+        return this.session.rpc(url, data, success, error);
+    },
+    do_action: function(action, on_finished) {
+        return this.controller_parent.do_action(action, on_finished);
+    }
+});
+
+instance.base.NivWidget = instance.base.Controller.extend({
+    /**
+     * The name of the QWeb template that will be used for rendering. Must be
+     * redefined in subclasses or the render() method can not be used.
+     * 
+     * @type string
+     */
+    template: null,
+    /**
+     * The prefix used to generate an id automatically. Should be redefined in
+     * subclasses. If it is not defined, a default identifier will be used.
+     * 
+     * @type string
+     */
+    identifier_prefix: 'generic-identifier',
+    /**
+     * Base class for widgets. Handle rendering (based on a QWeb template),
+     * identifier generation, parenting and destruction of the widget.
+     * Also initialize the identifier.
+     *
+     * @constructs
+     * @params {openerp.base.search.BaseWidget} parent The parent widget.
+     */
+    init: function(parent, element_id) {
+        this._super(parent);
+        this.make_id(this.identifier_prefix);
+        // this.element_id = element_id;
+        // this.$element = $('#' + element_id);
+        // if (element_id) {
+        //     instance.screen[element_id] = this;
+        // }
+        // save the parent children relationship
+        this.controller_children = [];
+        if(parent && parent.controller_children) {
+            parent.controller_children.push(this);
+        }
+        // backward compatibility
+        this.parent = this.controller_parent;
+        this.children = this.controller_children;
+
+    },
+    /**
+     * Event binding, rpc and callback calling required to initialize the
+     * object should happen here
+     *
+     * Returns a promise object letting callers (subclasses and direct callers)
+     * know when this component is done starting
+     *
+     * @returns {jQuery.Deferred}
+     */
+    /**
+     * "Starts" the widgets. Called at the end of the rendering, this allows
+     * to get a jQuery object referring to the DOM ($element attribute).
+     */
+    start: function () {
+        this._super();
+        var tmp = document.getElementById(this.element_id);
+        this.$element = tmp ? $(tmp) : null;
+    },
+    stop: function() {
+        if(this.$element != null) {
+            this.$element.remove();
+        }
+        if (this.parent && this.parent.children) {
+            this.parent.children = _.without(this.parent.children, this);
+            this.parent.controller_children = this.parent.children;
+        }
+        this.parent = null;
+        this.controller_parent = null;
+    },
+    /**
+     * Sets and returns a globally unique identifier for the widget.
+     *
+     * If a prefix is appended, the identifier will be appended to it.
+     *
+     * @params sections prefix sections, empty/falsy sections will be removed
+     */
+    make_id: function () {
+        this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
+        return this.element_id;
+    },
+    /**
+     * Render the widget. This.template must be defined.
+     * The content of the current object is passed as context to the template.
+     * 
+     * @param {object} additional Additional context arguments to pass to the template.
+     */
+    render: function (additional) {
+        return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {}));
+    },
+    widget_add: function(element, addfunc) {
+    },
+    widget_append: function(element) {
+    },
+    widget_prepend: function(element) {
+    },
+    widget_append2: function(element) {
+    },
+    widget_prepend2: function(element) {
+    },
+});
+
+
 };
 
 // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
-- 
cgit v1.2.3


From ccb48c8f4b2bab8345e1e80379b54b2f093954e8 Mon Sep 17 00:00:00 2001
From: niv-openerp 
Date: Thu, 28 Jul 2011 16:34:13 +0200
Subject: [imp] changed a lot of things in controller but stick with
 retro-compatibility

bzr revid: nicolas.vanhoren@openerp.com-20110728143413-7z0an78q6k5ytsiy
---
 addons/base/static/src/js/controller.js | 352 +++++---------------------------
 1 file changed, 54 insertions(+), 298 deletions(-)

(limited to 'addons/base/static/src/js/controller.js')

diff --git a/addons/base/static/src/js/controller.js b/addons/base/static/src/js/controller.js
index 1a13ab18607..a9bf99f8764 100644
--- a/addons/base/static/src/js/controller.js
+++ b/addons/base/static/src/js/controller.js
@@ -148,33 +148,14 @@ instance.base.generate_null_object_class = function(claz, add) {
 // --------------------------------------------------------
 // OLD 
 // --------------------------------------------------------
-
 /**
- * OpenERP Controller
- * TODO merge BaseWidget with Controller
+ * Class for OpenERP session aware classes to extend. Also provides callback mechanism and logging
+ * facility.
  */
-instance.base.Controller = instance.base.Class.extend( /** @lends instance.base.Controller# */{
-    /**
-     * @constructs
-     * rpc operations, event binding and callback calling should be done in
-     * start() instead of init so that events can be hooked in between.
-     */
-    init: function(parent, element_id) {
-        this.element_id = element_id;
-        this.$element = $('#' + element_id);
-        if (element_id) {
-            instance.screen[element_id] = this;
-        }
-        // save the parent children relationship
-        this.controller_parent = parent;
-        this.controller_children = [];
-        if(parent && parent.controller_children) {
-            parent.controller_children.push(this);
-        }
-        // backward compatibility
-        this.parent = this.controller_parent;
-        this.children = this.controller_children;
-
+instance.base.SessionAware = instance.base.Class.extend({
+    init: function(session) {
+        this.session = session;
+        
         // Transform on_* method into openerp.base.callbacks
         for (var name in this) {
             if(typeof(this[name]) == "function") {
@@ -186,78 +167,6 @@ instance.base.Controller = instance.base.Class.extend( /** @lends instance.base.
             }
         }
     },
-    /**
-     * Event binding, rpc and callback calling required to initialize the
-     * object should happen here
-     *
-     * Returns a promise object letting callers (subclasses and direct callers)
-     * know when this component is done starting
-     *
-     * @returns {jQuery.Deferred}
-     */
-    start: function() {
-        // returns an already fulfilled promise. Maybe we could return nothing?
-        // $.when can take non-deferred and in that case it simply considers
-        // them all as fulfilled promises.
-        // But in thise case we *have* to ensure callers use $.when and don't
-        // try to call deferred methods on this return value.
-        return $.Deferred().done().promise();
-    },
-    stop: function() {
-        if (this.parent && this.parent.children) {
-            this.parent.children = _.without(this.parent.children, this);
-            this.parent.controller_children = this.parent.children;
-        }
-        this.parent = null;
-        this.controller_parent = null;
-    },
-    log: function() {
-        var args = Array.prototype.slice.call(arguments);
-        var caller = arguments.callee.caller;
-        // TODO add support for line number using
-        // https://github.com/emwendelin/javascript-stacktrace/blob/master/stacktrace.js
-        // args.unshift("" + caller.debug_name);
-        this.on_log.apply(this,args);
-    },
-    on_log: function() {
-        if(window.openerp.debug || (window.location.search.indexOf('?debug') !== -1)) {
-            var notify = false;
-            var body = false;
-            if(window.console) {
-                console.log(arguments);
-            } else {
-                body = true;
-            }
-            var a = Array.prototype.slice.call(arguments, 0);
-            for(var i = 0; i < a.length; i++) {
-                var v = a[i]==null ? "null" : a[i].toString();
-                if(i==0) {
-                    notify = v.match(/^not/);
-                    body = v.match(/^bod/);
-                }
-                if(body) {
-                    $('
').text(v).appendTo($('body'));
-                }
-                if(notify && this.notification) {
-                    this.notification.notify("Logging:",v);
-                }
-            }
-        }
-
-    }
-});
-
-/**
- * OpenERP session aware controller
- * a controller takes an already existing dom element and manage it
- */
-instance.base.Controller = instance.base.Controller.extend( /** @lends openerp.base.Controller# */{
-    init: function(parent, element_id) {
-        this._super(parent, element_id);
-        if(this.controller_parent && this.controller_parent.session) {
-            this.session = this.controller_parent.session;
-        }
-    },
     /**
      * Performs a JSON-RPC call
      *
@@ -270,126 +179,6 @@ instance.base.Controller = instance.base.Controller.extend( /** @lends openerp.b
     rpc: function(url, data, success, error) {
         return this.session.rpc(url, data, success, error);
     },
-    do_action: function(action, on_finished) {
-        return this.parent.do_action(action, on_finished);
-    }
-});
-
-/**
- * OpenERP session aware widget
- * A widget is a controller that doesnt take an element_id
- * it render its own html render() that you should insert into the dom
- * and bind it at start()
- */
-instance.base.BaseWidget = instance.base.Controller.extend({
-    /**
-     * The name of the QWeb template that will be used for rendering. Must be
-     * redefined in subclasses or the render() method can not be used.
-     * 
-     * @type string
-     */
-    template: null,
-    /**
-     * The prefix used to generate an id automatically. Should be redefined in
-     * subclasses. If it is not defined, a default identifier will be used.
-     * 
-     * @type string
-     */
-    identifier_prefix: 'generic-identifier',
-    /**
-     * Base class for widgets. Handle rendering (based on a QWeb template),
-     * identifier generation, parenting and destruction of the widget.
-     * Also initialize the identifier.
-     *
-     * @constructs
-     * @params {openerp.base.search.BaseWidget} parent The parent widget.
-     */
-    init: function (parent) {
-        this._super(parent);
-        this.make_id(this.identifier_prefix);
-    },
-    /**
-     * Sets and returns a globally unique identifier for the widget.
-     *
-     * If a prefix is appended, the identifier will be appended to it.
-     *
-     * @params sections prefix sections, empty/falsy sections will be removed
-     */
-    make_id: function () {
-        this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
-        return this.element_id;
-    },
-    /**
-     * Render the widget. This.template must be defined.
-     * The content of the current object is passed as context to the template.
-     * 
-     * @param {object} additional Additional context arguments to pass to the template.
-     */
-    render: function (additional) {
-        return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {}));
-    },
-    /**
-     * "Starts" the widgets. Called at the end of the rendering, this allows
-     * to get a jQuery object referring to the DOM ($element attribute).
-     */
-    start: function () {
-        this._super();
-        var tmp = document.getElementById(this.element_id);
-        this.$element = tmp ? $(tmp) : null;
-    },
-    /**
-     * "Stops" the widgets. Called when the view destroys itself, this
-     * lets the widgets clean up after themselves.
-     */
-    stop: function () {
-        if(this.$element != null) {
-            this.$element.remove();
-        }
-        this._super();
-    }
-});
-
-// --------------------------------------------------------
-// N-style aka New-Style or Niv-Style
-// --------------------------------------------------------
-
-instance.base.NivController = instance.base.Class.extend({
-    init: function(parent) {
-        this.controller_parent = parent;
-        // Take the session of the parent if defined
-        if(this.controller_parent && this.controller_parent.session) {
-            this.session = this.controller_parent.session;
-        }
-        // Transform on_* method into openerp.base.callbacks
-        for (var name in this) {
-            if(typeof(this[name]) == "function") {
-                this[name].debug_name = name;
-                // bind ALL function to this not only on_and _do ?
-                if((/^on_|^do_/).test(name)) {
-                    this[name] = instance.base.callback(this, this[name]);
-                }
-            }
-        }
-    },
-    /**
-     * Event binding, rpc and callback calling required to initialize the
-     * object should happen here
-     *
-     * Returns a promise object letting callers (subclasses and direct callers)
-     * know when this component is done starting
-     *
-     * @returns {jQuery.Deferred}
-     */
-    start: function() {
-        // returns an already fulfilled promise. Maybe we could return nothing?
-        // $.when can take non-deferred and in that case it simply considers
-        // them all as fulfilled promises.
-        // But in thise case we *have* to ensure callers use $.when and don't
-        // try to call deferred methods on this return value.
-        return $.Deferred().done().promise();
-    },
-    stop: function() {
-    },
     log: function() {
         var args = Array.prototype.slice.call(arguments);
         var caller = arguments.callee.caller;
@@ -422,65 +211,54 @@ instance.base.NivController = instance.base.Class.extend({
                 }
             }
         }
-
-    },
-    /**
-     * Performs a JSON-RPC call
-     *
-     * @param {String} url endpoint url
-     * @param {Object} data RPC parameters
-     * @param {Function} success RPC call success callback
-     * @param {Function} error RPC call error callback
-     * @returns {jQuery.Deferred} deferred object for the RPC call
-     */
-    rpc: function(url, data, success, error) {
-        return this.session.rpc(url, data, success, error);
-    },
-    do_action: function(action, on_finished) {
-        return this.controller_parent.do_action(action, on_finished);
     }
 });
 
-instance.base.NivWidget = instance.base.Controller.extend({
+instance.base.Controller = instance.base.SessionAware.extend({
     /**
      * The name of the QWeb template that will be used for rendering. Must be
-     * redefined in subclasses or the render() method can not be used.
+     * redefined in subclasses or the default render() method can not be used.
      * 
      * @type string
      */
     template: null,
     /**
      * The prefix used to generate an id automatically. Should be redefined in
-     * subclasses. If it is not defined, a default identifier will be used.
+     * subclasses. If it is not defined, a generic identifier will be used.
      * 
      * @type string
      */
     identifier_prefix: 'generic-identifier',
     /**
-     * Base class for widgets. Handle rendering (based on a QWeb template),
-     * identifier generation, parenting and destruction of the widget.
-     * Also initialize the identifier.
-     *
      * @constructs
-     * @params {openerp.base.search.BaseWidget} parent The parent widget.
+     * rpc operations, event binding and callback calling should be done in
+     * start() instead of init so that events can be hooked in between.
      */
     init: function(parent, element_id) {
-        this._super(parent);
-        this.make_id(this.identifier_prefix);
-        // this.element_id = element_id;
-        // this.$element = $('#' + element_id);
-        // if (element_id) {
-        //     instance.screen[element_id] = this;
-        // }
+        this._super((parent || {}).session);
+        //TODO niv: get away the possibility to specify an id
+        this.element_id = element_id;
+        this.element_id = this.element_id || _.uniqueId(this.identifier_prefix);
+        
+        this.$element = $('#' + element_id);
+        if (element_id) {
+            instance.screen[element_id] = this;
+        }
         // save the parent children relationship
-        this.controller_children = [];
-        if(parent && parent.controller_children) {
-            parent.controller_children.push(this);
+        this.widget_parent = parent;
+        this.widget_children = [];
+        if(parent && parent.widget_children) {
+            parent.widget_children.push(this);
         }
-        // backward compatibility
-        this.parent = this.controller_parent;
-        this.children = this.controller_children;
-
+    },
+    /**
+     * Render the widget. This.template must be defined.
+     * The content of the current object is passed as context to the template.
+     * 
+     * @param {object} additional Additional context arguments to pass to the template.
+     */
+    render: function (additional) {
+        return QWeb.render(this.template, _.extend({widget: this}, additional || {}));
     },
     /**
      * Event binding, rpc and callback calling required to initialize the
@@ -491,59 +269,37 @@ instance.base.NivWidget = instance.base.Controller.extend({
      *
      * @returns {jQuery.Deferred}
      */
-    /**
-     * "Starts" the widgets. Called at the end of the rendering, this allows
-     * to get a jQuery object referring to the DOM ($element attribute).
-     */
-    start: function () {
-        this._super();
+    start: function() {
         var tmp = document.getElementById(this.element_id);
         this.$element = tmp ? $(tmp) : null;
+        return $.Deferred().done().promise();
     },
     stop: function() {
+        _.each(_.clone(this.widget_children), function(el) {
+            el.stop();
+        });
         if(this.$element != null) {
             this.$element.remove();
         }
-        if (this.parent && this.parent.children) {
-            this.parent.children = _.without(this.parent.children, this);
-            this.parent.controller_children = this.parent.children;
+        if (this.widget_parent && this.widget_parent.widget_children) {
+            this.widget_parent.widget_children = _.without(this.widget_parent.widget_children, this);
         }
-        this.parent = null;
-        this.controller_parent = null;
-    },
-    /**
-     * Sets and returns a globally unique identifier for the widget.
-     *
-     * If a prefix is appended, the identifier will be appended to it.
-     *
-     * @params sections prefix sections, empty/falsy sections will be removed
-     */
-    make_id: function () {
-        this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
-        return this.element_id;
-    },
-    /**
-     * Render the widget. This.template must be defined.
-     * The content of the current object is passed as context to the template.
-     * 
-     * @param {object} additional Additional context arguments to pass to the template.
-     */
-    render: function (additional) {
-        return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {}));
-    },
-    widget_add: function(element, addfunc) {
-    },
-    widget_append: function(element) {
-    },
-    widget_prepend: function(element) {
-    },
-    widget_append2: function(element) {
-    },
-    widget_prepend2: function(element) {
+        this.widget_parent = null;
     },
+    do_action: function(action, on_finished) {
+        return this.widget_parent.do_action(action, on_finished);
+    }
 });
 
+/*
+ * For retro compatibility only, the only difference with is that render takes
+ * directly this instead of 
+ */
+instance.base.BaseWidget = instance.base.Controller.extend({
+    render: function (additional) {
+        return QWeb.render(this.template, _.extend(_.extend({}, this), additional || {}));
+    }
+});
 
-};
-
+}
 // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
-- 
cgit v1.2.3


From 8e8ca695cb7136048e8d5c428c1daaf06af7f476 Mon Sep 17 00:00:00 2001
From: niv-openerp 
Date: Thu, 28 Jul 2011 16:49:12 +0200
Subject: [imp] changed Controller to Widget and BaseWidget to OldWidget

bzr revid: nicolas.vanhoren@openerp.com-20110728144912-t3kml1yo8gt261ga
---
 addons/base/static/src/js/controller.js | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'addons/base/static/src/js/controller.js')

diff --git a/addons/base/static/src/js/controller.js b/addons/base/static/src/js/controller.js
index a9bf99f8764..2ed00f29ff9 100644
--- a/addons/base/static/src/js/controller.js
+++ b/addons/base/static/src/js/controller.js
@@ -140,7 +140,7 @@ instance.base.generate_null_object_class = function(claz, add) {
             copy_proto(prototype.prototype);
     };
     copy_proto(claz.prototype);
-    newer.init = instance.base.Controller.prototype.init;
+    newer.init = instance.base.Widget.prototype.init;
     var tmpclass = claz.extend(newer);
     return tmpclass.extend(add || {});
 };
@@ -214,7 +214,7 @@ instance.base.SessionAware = instance.base.Class.extend({
     }
 });
 
-instance.base.Controller = instance.base.SessionAware.extend({
+instance.base.Widget = instance.base.SessionAware.extend({
     /**
      * The name of the QWeb template that will be used for rendering. Must be
      * redefined in subclasses or the default render() method can not be used.
@@ -295,7 +295,7 @@ instance.base.Controller = instance.base.SessionAware.extend({
  * For retro compatibility only, the only difference with is that render takes
  * directly this instead of 
  */
-instance.base.BaseWidget = instance.base.Controller.extend({
+instance.base.OldWidget = instance.base.Widget.extend({
     render: function (additional) {
         return QWeb.render(this.template, _.extend(_.extend({}, this), additional || {}));
     }
-- 
cgit v1.2.3


From 2ba74a4c8a0841347578c1038e1374318ba118f5 Mon Sep 17 00:00:00 2001
From: niv-openerp 
Date: Thu, 28 Jul 2011 17:24:56 +0200
Subject: [imp] Mainly documentation and small modifications to Widget.

bzr revid: nicolas.vanhoren@openerp.com-20110728152456-2mgkbcqhm7d0zz3m
---
 addons/base/static/src/js/controller.js | 74 ++++++++++++++++++++++++---------
 1 file changed, 55 insertions(+), 19 deletions(-)

(limited to 'addons/base/static/src/js/controller.js')

diff --git a/addons/base/static/src/js/controller.js b/addons/base/static/src/js/controller.js
index 2ed00f29ff9..7abf35c10ed 100644
--- a/addons/base/static/src/js/controller.js
+++ b/addons/base/static/src/js/controller.js
@@ -149,8 +149,10 @@ instance.base.generate_null_object_class = function(claz, add) {
 // OLD 
 // --------------------------------------------------------
 /**
- * Class for OpenERP session aware classes to extend. Also provides callback mechanism and logging
- * facility.
+ * Utility class that any class is allowed to extend to easy common manipulations.
+ * 
+ * It provides rpc calls, callback on all methods preceded by "on_" or "do_" and a
+ * logging facility.
  */
 instance.base.SessionAware = instance.base.Class.extend({
     init: function(session) {
@@ -214,6 +216,18 @@ instance.base.SessionAware = instance.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.
+ */
 instance.base.Widget = instance.base.SessionAware.extend({
     /**
      * The name of the QWeb template that will be used for rendering. Must be
@@ -231,16 +245,24 @@ instance.base.Widget = instance.base.SessionAware.extend({
     identifier_prefix: 'generic-identifier',
     /**
      * @constructs
-     * rpc operations, event binding and callback calling should be done in
-     * start() instead of init so that events can be hooked in between.
+     * Construct the widget and set its parent if a parent is given.
+     * 
+     * @param {Widget} parent Binds the current instance to the given Widget instance.
+     * When that widget is destroyed by calling stop(), the current instance will be
+     * destroyed too. Can be null.
+     * @param {String} element_id Deprecated. Sets the element_id. Only useful when you want
+     * to bind the current Widget to an already existing part of the DOM, which is not compatible
+     * with the DOM insertion methods provided by the current implementation of Widget. So
+     * for new components this argument should not be provided any more.
      */
     init: function(parent, element_id) {
         this._super((parent || {}).session);
-        //TODO niv: get away the possibility to specify an id
         this.element_id = element_id;
         this.element_id = this.element_id || _.uniqueId(this.identifier_prefix);
         
-        this.$element = $('#' + element_id);
+        var tmp = document.getElementById(this.element_id);
+        this.$element = tmp ? $(tmp) : undefined;
+        // TODO niv: wtf??
         if (element_id) {
             instance.screen[element_id] = this;
         }
@@ -252,8 +274,8 @@ instance.base.Widget = instance.base.SessionAware.extend({
         }
     },
     /**
-     * Render the widget. This.template must be defined.
-     * The content of the current object is passed as context to the template.
+     * Renders the widget using QWeb, `this.template` must be defined.
+     * The context given to QWeb contains the "widget" key that references `this`.
      * 
      * @param {object} additional Additional context arguments to pass to the template.
      */
@@ -261,19 +283,24 @@ instance.base.Widget = instance.base.SessionAware.extend({
         return QWeb.render(this.template, _.extend({widget: this}, additional || {}));
     },
     /**
-     * Event binding, rpc and callback calling required to initialize the
-     * object should happen here
-     *
-     * Returns a promise object letting callers (subclasses and direct callers)
-     * know when this component is done starting
+     * Method called after rendering. Mostly used to bind actions, perform asynchronous
+     * calls, etc...
+     * 
+     * By convention, the method should return a promise to inform the caller when
+     * this widget has been initialized.
      *
      * @returns {jQuery.Deferred}
      */
     start: function() {
-        var tmp = document.getElementById(this.element_id);
-        this.$element = tmp ? $(tmp) : null;
+        if (!this.$element) {
+            var tmp = document.getElementById(this.element_id);
+            this.$element = tmp ? $(tmp) : undefined;
+        }
         return $.Deferred().done().promise();
     },
+    /**
+     * Destroys the current widget, also destory all its children before destroying itself.
+     */
     stop: function() {
         _.each(_.clone(this.widget_children), function(el) {
             el.stop();
@@ -286,14 +313,23 @@ instance.base.Widget = instance.base.SessionAware.extend({
         }
         this.widget_parent = null;
     },
+    /**
+     * Inform the action manager to do an action. Of course, this suppose that
+     * the action manager can be found amongst the ancestors of the current widget.
+     * If that's not the case this method will simply return `false`.
+     */
     do_action: function(action, on_finished) {
-        return this.widget_parent.do_action(action, on_finished);
+        if (this.widget_parent) {
+            return this.widget_parent.do_action(action, on_finished);
+        }
+        return false;
     }
 });
 
-/*
- * For retro compatibility only, the only difference with is that render takes
- * directly this instead of 
+/**
+ * @deprecated
+ * For retro compatibility only, the only difference with is that render() uses
+ * directly this instead of a {widget: this}.
  */
 instance.base.OldWidget = instance.base.Widget.extend({
     render: function (additional) {
-- 
cgit v1.2.3


From a64f68bd2027ea6bce02156c5eeafa9e8625e638 Mon Sep 17 00:00:00 2001
From: niv-openerp 
Date: Thu, 28 Jul 2011 18:59:14 +0200
Subject: [imp] DOM insertion methods for Widget + doc + rpc stop mechanism

bzr revid: nicolas.vanhoren@openerp.com-20110728165914-6nadrs5sj00jd91j
---
 addons/base/static/src/js/controller.js | 122 +++++++++++++++++++++++++++++---
 1 file changed, 113 insertions(+), 9 deletions(-)

(limited to 'addons/base/static/src/js/controller.js')

diff --git a/addons/base/static/src/js/controller.js b/addons/base/static/src/js/controller.js
index 7abf35c10ed..0684f7407d2 100644
--- a/addons/base/static/src/js/controller.js
+++ b/addons/base/static/src/js/controller.js
@@ -227,6 +227,46 @@ instance.base.SessionAware = instance.base.Class.extend({
  * - Insertion in DOM.
  * 
  * Widget also extends SessionAware for ease of use.
+ * 
+ * Guide to create implementations of this 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, 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() {
+ *         // stuff you want to make after the rendering, `this.$element` holds a 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.
  */
 instance.base.Widget = instance.base.SessionAware.extend({
     /**
@@ -242,7 +282,7 @@ instance.base.Widget = instance.base.SessionAware.extend({
      * 
      * @type string
      */
-    identifier_prefix: 'generic-identifier',
+    identifier_prefix: 'generic-identifier-',
     /**
      * @constructs
      * Construct the widget and set its parent if a parent is given.
@@ -255,23 +295,74 @@ instance.base.Widget = instance.base.SessionAware.extend({
      * with the DOM insertion methods provided by the current implementation of Widget. So
      * for new components this argument should not be provided any more.
      */
-    init: function(parent, element_id) {
+    init: function(parent, /** @deprecated */ element_id) {
         this._super((parent || {}).session);
+        // if given an element_id, try to get the associated DOM element and save
+        // a reference in this.$element. Else just generate a unique identifier.
         this.element_id = element_id;
         this.element_id = this.element_id || _.uniqueId(this.identifier_prefix);
-        
         var tmp = document.getElementById(this.element_id);
         this.$element = tmp ? $(tmp) : undefined;
-        // TODO niv: wtf??
-        if (element_id) {
-            instance.screen[element_id] = this;
-        }
-        // save the parent children relationship
+        
         this.widget_parent = parent;
         this.widget_children = [];
         if(parent && parent.widget_children) {
             parent.widget_children.push(this);
         }
+        // useful to know if the widget was destroyed and should not be used anymore
+        this.widget_is_stopped = false;
+    },
+    /**
+     * Render the current widget and appends it to the given jQuery object or Widget.
+     * 
+     * @param target A jQuery object or a Widget instance.
+     */
+    appendTo: function(target) {
+        var self = this;
+        return this._render_and_insert(function(t) {
+            self.$element.appendTo(t);
+        }, target);
+    },
+    /**
+     * Render the current widget and prepends it to the given jQuery object or Widget.
+     * 
+     * @param target A jQuery object or a Widget instance.
+     */
+    prependTo: function(target) {
+        var self = this;
+        return this._render_and_insert(function(t) {
+            self.$element.prependTo(t);
+        }, target);
+    },
+    /**
+     * Render the current widget and inserts it after to the given jQuery object or Widget.
+     * 
+     * @param target A jQuery object or a Widget instance.
+     */
+    insertAfter: function(target) {
+        var self = this;
+        return this._render_and_insert(function(t) {
+            self.$element.insertAfter(t);
+        }, target);
+    },
+    /**
+     * Render the current widget and inserts it before to the given jQuery object or Widget.
+     * 
+     * @param target A jQuery object or a Widget instance.
+     */
+    insertBefore: function(target) {
+        var self = this;
+        return this._render_and_insert(function(t) {
+            self.$element.insertBefore(t);
+        }, target);
+    },
+    _render_and_insert: function(insertion, target) {
+        var rendered = this.render();
+        this.$element = $(rendered);
+        if (target instanceof instance.base.Widget)
+            target = target.$element;
+        insertion(target);
+        return this.start();
     },
     /**
      * Renders the widget using QWeb, `this.template` must be defined.
@@ -312,6 +403,7 @@ instance.base.Widget = instance.base.SessionAware.extend({
             this.widget_parent.widget_children = _.without(this.widget_parent.widget_children, this);
         }
         this.widget_parent = null;
+        this.widget_is_stopped = true;
     },
     /**
      * Inform the action manager to do an action. Of course, this suppose that
@@ -323,13 +415,25 @@ instance.base.Widget = instance.base.SessionAware.extend({
             return this.widget_parent.do_action(action, on_finished);
         }
         return false;
+    },
+    rpc: function(url, data, success, error) {
+        var def = $.Deferred().then(success, error);
+        var self = this;
+        this._super(url, data). then(function() {
+            if (!self.widget_is_stopped)
+                def.resolve.apply(def, arguments);
+        }, function() {
+            if (!self.widget_is_stopped)
+                def.reject.apply(def, arguments);
+        });
+        return def.promise();
     }
 });
 
 /**
  * @deprecated
  * For retro compatibility only, the only difference with is that render() uses
- * directly this instead of a {widget: this}.
+ * directly `this` instead of context with a "widget" key.
  */
 instance.base.OldWidget = instance.base.Widget.extend({
     render: function (additional) {
-- 
cgit v1.2.3


From 0111cf3fd5c94c929e3196ff73a83715ff675af8 Mon Sep 17 00:00:00 2001
From: Antony Lesuisse 
Date: Fri, 29 Jul 2011 14:40:16 +0200
Subject: [IMP] rename controller.js to core.js

bzr revid: al@openerp.com-20110729124016-gvtayplemywiyh0a
---
 addons/base/static/src/js/controller.js | 445 --------------------------------
 1 file changed, 445 deletions(-)
 delete mode 100644 addons/base/static/src/js/controller.js

(limited to 'addons/base/static/src/js/controller.js')

diff --git a/addons/base/static/src/js/controller.js b/addons/base/static/src/js/controller.js
deleted file mode 100644
index 0684f7407d2..00000000000
--- a/addons/base/static/src/js/controller.js
+++ /dev/null
@@ -1,445 +0,0 @@
-/*---------------------------------------------------------
- * OpenERP controller framework
- *--------------------------------------------------------*/
-
-openerp.base.controller = function(instance) {
-/**
- * John Resig Class with factory improvement
- */
-(function() {
-  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
-  // The base Class implementation (does nothing)
-  this.Class = function(){};
-
-  // Create a new Class that inherits from this class
-  Class.extend = function(prop) {
-    var _super = this.prototype;
-
-    // Instantiate a base class (but only create the instance,
-    // don't run the init constructor)
-    initializing = true;
-    var prototype = new this();
-    initializing = false;
-
-    // Copy the properties over onto the new prototype
-    for (var name in prop) {
-      // Check if we're overwriting an existing function
-      prototype[name] = typeof prop[name] == "function" && 
-        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
-        (function(name, fn){
-          return function() {
-            var tmp = this._super;
-
-            // Add a new ._super() method that is the same method
-            // but on the super-class
-            this._super = _super[name];
-
-            // The method only need to be bound temporarily, so we
-            // remove it when we're done executing
-            var ret = fn.apply(this, arguments);
-            this._super = tmp;
-
-            return ret;
-          };
-        })(name, prop[name]) :
-        prop[name];
-    }
-
-    // The dummy class constructor
-    function Class() {
-      // All construction is actually done in the init method
-      if ( !initializing && this.init ) {
-        var ret = this.init.apply(this, arguments);
-        if (ret) { return ret; }
-      }
-      return this;
-    }
-
-    // Populate our constructed prototype object
-    Class.prototype = prototype;
-
-    // Enforce the constructor to be what we expect
-    Class.constructor = Class;
-
-    // And make this class extendable
-    Class.extend = arguments.callee;
-
-    return Class;
-  };
-})();
-
-// todo change john resig class to keep window clean
-instance.base.Class = window.Class
-
-instance.base.callback = function(obj, method) {
-    var callback = function() {
-        var args = Array.prototype.slice.call(arguments);
-        var r;
-        for(var i = 0; i < callback.callback_chain.length; i++)  {
-            var c = callback.callback_chain[i];
-            if(c.unique) {
-                callback.callback_chain.splice(i, 1);
-                i -= 1;
-            }
-            r = c.callback.apply(c.self, c.args.concat(args));
-            // TODO special value to stop the chain
-            // openerp.base.callback_stop
-        }
-        return r;
-    };
-    callback.callback_chain = [];
-    callback.add = function(f) {
-        if(typeof(f) == 'function') {
-            f = { callback: f, args: Array.prototype.slice.call(arguments, 1) };
-        }
-        f.self = f.self || null;
-        f.args = f.args || [];
-        f.unique = !!f.unique;
-        if(f.position == 'last') {
-            callback.callback_chain.push(f);
-        } else {
-            callback.callback_chain.unshift(f);
-        }
-        return callback;
-    };
-    callback.add_first = function(f) {
-        return callback.add.apply(null,arguments);
-    };
-    callback.add_last = function(f) {
-        return callback.add({
-            callback: f,
-            args: Array.prototype.slice.call(arguments, 1),
-            position: "last"
-        });
-    };
-
-    return callback.add({
-        callback: method,
-        self:obj,
-        args:Array.prototype.slice.call(arguments, 2)
-    });
-};
-
-/**
- * Generates an inherited class that replaces all the methods by null methods (methods
- * that does nothing and always return undefined).
- * 
- * @param {Class} claz
- * @param {dict} add Additional functions to override.
- * @return {Class}
- */
-instance.base.generate_null_object_class = function(claz, add) {
-    var newer = {};
-    var copy_proto = function(prototype) {
-        for (var name in prototype) {
-            if(typeof prototype[name] == "function") {
-                newer[name] = function() {};
-            }
-        }
-        if (prototype.prototype)
-            copy_proto(prototype.prototype);
-    };
-    copy_proto(claz.prototype);
-    newer.init = instance.base.Widget.prototype.init;
-    var tmpclass = claz.extend(newer);
-    return tmpclass.extend(add || {});
-};
-
-// --------------------------------------------------------
-// OLD 
-// --------------------------------------------------------
-/**
- * Utility class that any class is allowed to extend to easy common manipulations.
- * 
- * It provides rpc calls, callback on all methods preceded by "on_" or "do_" and a
- * logging facility.
- */
-instance.base.SessionAware = instance.base.Class.extend({
-    init: function(session) {
-        this.session = session;
-        
-        // Transform on_* method into openerp.base.callbacks
-        for (var name in this) {
-            if(typeof(this[name]) == "function") {
-                this[name].debug_name = name;
-                // bind ALL function to this not only on_and _do ?
-                if((/^on_|^do_/).test(name)) {
-                    this[name] = instance.base.callback(this, this[name]);
-                }
-            }
-        }
-    },
-    /**
-     * Performs a JSON-RPC call
-     *
-     * @param {String} url endpoint url
-     * @param {Object} data RPC parameters
-     * @param {Function} success RPC call success callback
-     * @param {Function} error RPC call error callback
-     * @returns {jQuery.Deferred} deferred object for the RPC call
-     */
-    rpc: function(url, data, success, error) {
-        return this.session.rpc(url, data, success, error);
-    },
-    log: function() {
-        var args = Array.prototype.slice.call(arguments);
-        var caller = arguments.callee.caller;
-        // TODO add support for line number using
-        // https://github.com/emwendelin/javascript-stacktrace/blob/master/stacktrace.js
-        // args.unshift("" + caller.debug_name);
-        this.on_log.apply(this,args);
-    },
-    on_log: function() {
-        if(window.openerp.debug || (window.location.search.indexOf('?debug') !== -1)) {
-            var notify = false;
-            var body = false;
-            if(window.console) {
-                console.log(arguments);
-            } else {
-                body = true;
-            }
-            var a = Array.prototype.slice.call(arguments, 0);
-            for(var i = 0; i < a.length; i++) {
-                var v = a[i]==null ? "null" : a[i].toString();
-                if(i==0) {
-                    notify = v.match(/^not/);
-                    body = v.match(/^bod/);
-                }
-                if(body) {
-                    $('
').text(v).appendTo($('body'));
-                }
-                if(notify && this.notification) {
-                    this.notification.notify("Logging:",v);
-                }
-            }
-        }
-    }
-});
-
-/**
- * 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 this 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, 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() {
- *         // stuff you want to make after the rendering, `this.$element` holds a 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.
- */
-instance.base.Widget = instance.base.SessionAware.extend({
-    /**
-     * The name of the QWeb template that will be used for rendering. Must be
-     * redefined in subclasses or the default render() method can not be used.
-     * 
-     * @type string
-     */
-    template: null,
-    /**
-     * The prefix used to generate an id automatically. Should be redefined in
-     * subclasses. If it is not defined, a generic identifier will be used.
-     * 
-     * @type string
-     */
-    identifier_prefix: 'generic-identifier-',
-    /**
-     * @constructs
-     * Construct the widget and set its parent if a parent is given.
-     * 
-     * @param {Widget} parent Binds the current instance to the given Widget instance.
-     * When that widget is destroyed by calling stop(), the current instance will be
-     * destroyed too. Can be null.
-     * @param {String} element_id Deprecated. Sets the element_id. Only useful when you want
-     * to bind the current Widget to an already existing part of the DOM, which is not compatible
-     * with the DOM insertion methods provided by the current implementation of Widget. So
-     * for new components this argument should not be provided any more.
-     */
-    init: function(parent, /** @deprecated */ element_id) {
-        this._super((parent || {}).session);
-        // if given an element_id, try to get the associated DOM element and save
-        // a reference in this.$element. Else just generate a unique identifier.
-        this.element_id = element_id;
-        this.element_id = this.element_id || _.uniqueId(this.identifier_prefix);
-        var tmp = document.getElementById(this.element_id);
-        this.$element = tmp ? $(tmp) : undefined;
-        
-        this.widget_parent = parent;
-        this.widget_children = [];
-        if(parent && parent.widget_children) {
-            parent.widget_children.push(this);
-        }
-        // useful to know if the widget was destroyed and should not be used anymore
-        this.widget_is_stopped = false;
-    },
-    /**
-     * Render the current widget and appends it to the given jQuery object or Widget.
-     * 
-     * @param target A jQuery object or a Widget instance.
-     */
-    appendTo: function(target) {
-        var self = this;
-        return this._render_and_insert(function(t) {
-            self.$element.appendTo(t);
-        }, target);
-    },
-    /**
-     * Render the current widget and prepends it to the given jQuery object or Widget.
-     * 
-     * @param target A jQuery object or a Widget instance.
-     */
-    prependTo: function(target) {
-        var self = this;
-        return this._render_and_insert(function(t) {
-            self.$element.prependTo(t);
-        }, target);
-    },
-    /**
-     * Render the current widget and inserts it after to the given jQuery object or Widget.
-     * 
-     * @param target A jQuery object or a Widget instance.
-     */
-    insertAfter: function(target) {
-        var self = this;
-        return this._render_and_insert(function(t) {
-            self.$element.insertAfter(t);
-        }, target);
-    },
-    /**
-     * Render the current widget and inserts it before to the given jQuery object or Widget.
-     * 
-     * @param target A jQuery object or a Widget instance.
-     */
-    insertBefore: function(target) {
-        var self = this;
-        return this._render_and_insert(function(t) {
-            self.$element.insertBefore(t);
-        }, target);
-    },
-    _render_and_insert: function(insertion, target) {
-        var rendered = this.render();
-        this.$element = $(rendered);
-        if (target instanceof instance.base.Widget)
-            target = target.$element;
-        insertion(target);
-        return this.start();
-    },
-    /**
-     * Renders the widget using QWeb, `this.template` must be defined.
-     * The context given to QWeb contains the "widget" key that references `this`.
-     * 
-     * @param {object} additional Additional context arguments to pass to the template.
-     */
-    render: function (additional) {
-        return QWeb.render(this.template, _.extend({widget: this}, additional || {}));
-    },
-    /**
-     * Method called after rendering. Mostly used to bind actions, perform asynchronous
-     * calls, etc...
-     * 
-     * By convention, the method should return a promise to inform the caller when
-     * this widget has been initialized.
-     *
-     * @returns {jQuery.Deferred}
-     */
-    start: function() {
-        if (!this.$element) {
-            var tmp = document.getElementById(this.element_id);
-            this.$element = tmp ? $(tmp) : undefined;
-        }
-        return $.Deferred().done().promise();
-    },
-    /**
-     * Destroys the current widget, also destory all its children before destroying itself.
-     */
-    stop: function() {
-        _.each(_.clone(this.widget_children), function(el) {
-            el.stop();
-        });
-        if(this.$element != null) {
-            this.$element.remove();
-        }
-        if (this.widget_parent && this.widget_parent.widget_children) {
-            this.widget_parent.widget_children = _.without(this.widget_parent.widget_children, this);
-        }
-        this.widget_parent = null;
-        this.widget_is_stopped = true;
-    },
-    /**
-     * Inform the action manager to do an action. Of course, this suppose that
-     * the action manager can be found amongst the ancestors of the current widget.
-     * If that's not the case this method will simply return `false`.
-     */
-    do_action: function(action, on_finished) {
-        if (this.widget_parent) {
-            return this.widget_parent.do_action(action, on_finished);
-        }
-        return false;
-    },
-    rpc: function(url, data, success, error) {
-        var def = $.Deferred().then(success, error);
-        var self = this;
-        this._super(url, data). then(function() {
-            if (!self.widget_is_stopped)
-                def.resolve.apply(def, arguments);
-        }, function() {
-            if (!self.widget_is_stopped)
-                def.reject.apply(def, arguments);
-        });
-        return def.promise();
-    }
-});
-
-/**
- * @deprecated
- * For retro compatibility only, the only difference with is that render() uses
- * directly `this` instead of context with a "widget" key.
- */
-instance.base.OldWidget = instance.base.Widget.extend({
-    render: function (additional) {
-        return QWeb.render(this.template, _.extend(_.extend({}, this), additional || {}));
-    }
-});
-
-}
-// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
-- 
cgit v1.2.3