diff options
Diffstat (limited to 'addons/base/static/src/js/controller.js')
| -rw-r--r-- | addons/base/static/src/js/controller.js | 122 |
1 files changed, 113 insertions, 9 deletions
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) { |
