[imp] DOM insertion methods for Widget + doc + rpc stop mechanism

bzr revid: nicolas.vanhoren@openerp.com-20110728165914-6nadrs5sj00jd91j
This commit is contained in:
niv-openerp 2011-07-28 18:59:14 +02:00
parent 2ba74a4c8a
commit a64f68bd20
2 changed files with 114 additions and 12 deletions

View File

@ -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) {

View File

@ -860,9 +860,7 @@ openerp.base.search.ExtendedSearch = openerp.base.OldWidget.extend({
},
add_group: function() {
var group = new openerp.base.search.ExtendedSearchGroup(this, this.fields);
var render = group.render();
this.$element.find('.searchview_extended_groups_list').append(render);
group.start();
group.appendTo(this.$element.find('.searchview_extended_groups_list'));
this.check_last_element();
},
start: function () {