[MERGE] core api improvements: remove callbackenabled, widgetmixin
bzr revid: al@openerp.com-20121110195411-01ffp20dmaikot71
This commit is contained in:
commit
cd4b9409f8
|
@ -189,7 +189,7 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
}
|
||||
});
|
||||
|
||||
instance.web.CrashManager = instance.web.CallbackEnabled.extend({
|
||||
instance.web.CrashManager = instance.web.Class.extend({
|
||||
rpc_error: function(error) {
|
||||
if (error.data.fault_code) {
|
||||
var split = ("" + error.data.fault_code).split('\n')[0].split(' -- ');
|
||||
|
|
|
@ -243,15 +243,17 @@ instance.web.ParentedMixin = {
|
|||
|
||||
/**
|
||||
* Backbone's events. Do not ever use it directly, use EventDispatcherMixin instead.
|
||||
*
|
||||
* This class just handle the dispatching of events, it is not meant to be extended,
|
||||
* nor used directly. All integration with parenting and automatic unregistration of
|
||||
* events is done in EventDispatcherMixin.
|
||||
*
|
||||
* Copyright notice for the following Class:
|
||||
*
|
||||
* (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
* Backbone may be freely distributed under the MIT license.
|
||||
* For all details and documentation:
|
||||
* http://backbonejs.org
|
||||
*
|
||||
* This class just handle the dispatching of events, it is not meant to be extended,
|
||||
* nor used directly. All integration with parenting and automatic unregistration of
|
||||
* events is done in EventDispatcherMixin.
|
||||
*
|
||||
*/
|
||||
var Events = instance.web.Class.extend({
|
||||
|
@ -334,7 +336,6 @@ var Events = instance.web.Class.extend({
|
|||
return this;
|
||||
}
|
||||
});
|
||||
// end of Jeremy Ashkenas' code
|
||||
|
||||
instance.web.EventDispatcherMixin = _.extend({}, instance.web.ParentedMixin, {
|
||||
__eventDispatcherMixin: true,
|
||||
|
@ -426,66 +427,94 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
|
|||
}
|
||||
});
|
||||
|
||||
instance.web.CallbackEnabledMixin = _.extend({}, instance.web.PropertiesMixin, {
|
||||
init: function() {
|
||||
instance.web.PropertiesMixin.init.call(this);
|
||||
var self = this;
|
||||
// Transform on_/do_* methods into callbacks
|
||||
var callback_maker = function(fn) {
|
||||
return function() {
|
||||
return fn.apply(self, arguments);
|
||||
}
|
||||
};
|
||||
for (var name in this) {
|
||||
if(typeof(this[name]) == "function") {
|
||||
if((/^on_|^do_/).test(name)) {
|
||||
this[name] = callback_maker(this[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Proxies a method of the object, in order to keep the right ``this`` on
|
||||
* method invocations.
|
||||
*
|
||||
* This method is similar to ``Function.prototype.bind`` or ``_.bind``, and
|
||||
* even more so to ``jQuery.proxy`` with a fundamental difference: its
|
||||
* resolution of the method being called is lazy, meaning it will use the
|
||||
* method as it is when the proxy is called, not when the proxy is created.
|
||||
*
|
||||
* Other methods will fix the bound method to what it is when creating the
|
||||
* binding/proxy, which is fine in most javascript code but problematic in
|
||||
* OpenERP Web where developers may want to replace existing callbacks with
|
||||
* theirs.
|
||||
*
|
||||
* The semantics of this precisely replace closing over the method call.
|
||||
*
|
||||
* @param {String|Function} method function or name of the method to invoke
|
||||
* @returns {Function} proxied method
|
||||
*/
|
||||
proxy: function (method) {
|
||||
var self = this;
|
||||
return function () {
|
||||
var fn = (typeof method === 'string') ? self[method] : method;
|
||||
return fn.apply(self, arguments);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Classes
|
||||
|
||||
instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* Guide to create implementations of the Widget class:
|
||||
* ==============================================
|
||||
*
|
||||
* Here is a sample child class:
|
||||
*
|
||||
* MyWidget = instance.base.Widget.extend({
|
||||
* // the name of the QWeb template to use for rendering
|
||||
* template: "MyQWebTemplate",
|
||||
*
|
||||
* 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.$el` holds a correct value
|
||||
* this.$el.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.destroy();
|
||||
*
|
||||
* That will kill the widget in a clean way and erase its content from the dom.
|
||||
*/
|
||||
instance.web.Widget = instance.web.Class.extend(instance.web.PropertiesMixin, {
|
||||
// Backbone-ish API
|
||||
tagName: 'div',
|
||||
id: null,
|
||||
className: null,
|
||||
attributes: {},
|
||||
events: {},
|
||||
/**
|
||||
* 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,
|
||||
/**
|
||||
* Constructs the widget and sets its parent if a parent is given.
|
||||
*
|
||||
* @constructs instance.web.Widget
|
||||
* @extends instance.web.CallbackEnabled
|
||||
*
|
||||
* @param {instance.web.Widget} parent Binds the current instance to the given Widget instance.
|
||||
* When that widget is destroyed by calling destroy(), the current instance will be
|
||||
* destroyed too. Can be null.
|
||||
*/
|
||||
init: function(parent) {
|
||||
instance.web.CallbackEnabledMixin.init.call(this);
|
||||
instance.web.PropertiesMixin.init.call(this);
|
||||
this.setParent(parent);
|
||||
// Bind on_/do_* methods to this
|
||||
// We might remove this automatic binding in the future
|
||||
for (var name in this) {
|
||||
if(typeof(this[name]) == "function") {
|
||||
if((/^on_|^do_/).test(name)) {
|
||||
this[name] = this[name].bind(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME: this should not be
|
||||
this.setElement(this._make_descriptive());
|
||||
this.session = instance.session;
|
||||
},
|
||||
/**
|
||||
* Destroys the current widget, also destroys all its children before destroying itself.
|
||||
|
@ -574,94 +603,32 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, {
|
|||
*/
|
||||
start: function() {
|
||||
return $.when();
|
||||
}
|
||||
});
|
||||
|
||||
// Classes
|
||||
|
||||
instance.web.CallbackEnabled = instance.web.Class.extend(instance.web.CallbackEnabledMixin, {
|
||||
init: function() {
|
||||
instance.web.CallbackEnabledMixin.init.call(this);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* Guide to create implementations of the Widget class:
|
||||
* ==============================================
|
||||
*
|
||||
* Here is a sample child class:
|
||||
*
|
||||
* MyWidget = instance.base.Widget.extend({
|
||||
* // the name of the QWeb template to use for rendering
|
||||
* template: "MyQWebTemplate",
|
||||
*
|
||||
* 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.$el` holds a correct value
|
||||
* this.$el.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.destroy();
|
||||
*
|
||||
* That will kill the widget in a clean way and erase its content from the dom.
|
||||
*/
|
||||
instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, {
|
||||
// Backbone-ish API
|
||||
tagName: 'div',
|
||||
id: null,
|
||||
className: null,
|
||||
attributes: {},
|
||||
events: {},
|
||||
},
|
||||
/**
|
||||
* 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.
|
||||
* Proxies a method of the object, in order to keep the right ``this`` on
|
||||
* method invocations.
|
||||
*
|
||||
* @type string
|
||||
* This method is similar to ``Function.prototype.bind`` or ``_.bind``, and
|
||||
* even more so to ``jQuery.proxy`` with a fundamental difference: its
|
||||
* resolution of the method being called is lazy, meaning it will use the
|
||||
* method as it is when the proxy is called, not when the proxy is created.
|
||||
*
|
||||
* Other methods will fix the bound method to what it is when creating the
|
||||
* binding/proxy, which is fine in most javascript code but problematic in
|
||||
* OpenERP Web where developers may want to replace existing callbacks with
|
||||
* theirs.
|
||||
*
|
||||
* The semantics of this precisely replace closing over the method call.
|
||||
*
|
||||
* @param {String|Function} method function or name of the method to invoke
|
||||
* @returns {Function} proxied method
|
||||
*/
|
||||
template: null,
|
||||
/**
|
||||
* Constructs the widget and sets its parent if a parent is given.
|
||||
*
|
||||
* @constructs instance.web.Widget
|
||||
* @extends instance.web.CallbackEnabled
|
||||
*
|
||||
* @param {instance.web.Widget} parent Binds the current instance to the given Widget instance.
|
||||
* When that widget is destroyed by calling destroy(), the current instance will be
|
||||
* destroyed too. Can be null.
|
||||
*/
|
||||
init: function(parent) {
|
||||
instance.web.WidgetMixin.init.call(this,parent);
|
||||
// FIXME: this should not be
|
||||
this.setElement(this._make_descriptive());
|
||||
this.session = instance.session;
|
||||
proxy: function (method) {
|
||||
var self = this;
|
||||
return function () {
|
||||
var fn = (typeof method === 'string') ? self[method] : method;
|
||||
return fn.apply(self, arguments);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Renders the element. The default implementation renders the widget using QWeb,
|
||||
|
@ -678,7 +645,6 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, {
|
|||
}
|
||||
this.replaceElement($el);
|
||||
},
|
||||
|
||||
/**
|
||||
* Re-sets the widget's root element and replaces the old root element
|
||||
* (if any) by the new one in the DOM.
|
||||
|
@ -941,7 +907,7 @@ instance.web.Registry = instance.web.Class.extend({
|
|||
}
|
||||
});
|
||||
|
||||
instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
||||
instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, {
|
||||
triggers: {
|
||||
'request': 'Request sent',
|
||||
'response': 'Response received',
|
||||
|
@ -950,13 +916,12 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
},
|
||||
/**
|
||||
* @constructs instance.web.JsonRPC
|
||||
* @extends instance.web.CallbackEnabled
|
||||
*
|
||||
* @param {String} [server] JSON-RPC endpoint hostname
|
||||
* @param {String} [port] JSON-RPC endpoint port
|
||||
*/
|
||||
init: function() {
|
||||
this._super();
|
||||
instance.web.PropertiesMixin.init.call(this);
|
||||
this.server = null;
|
||||
this.debug = ($.deparam($.param.querystring()).debug != undefined);
|
||||
},
|
||||
|
|
|
@ -53,7 +53,7 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
this.session_id = this.get_cookie('session_id');
|
||||
return this.session_reload().then(function(result) {
|
||||
var modules = instance._modules.join(',');
|
||||
var deferred = self.rpc('/web/webclient/qweblist', {mods: modules}).then(self.do_load_qweb);
|
||||
var deferred = self.rpc('/web/webclient/qweblist', {mods: modules}).then(self.load_qweb.bind(self));
|
||||
if(self.session_is_valid()) {
|
||||
return deferred.then(function() { return self.load_modules(); });
|
||||
}
|
||||
|
@ -168,15 +168,15 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
if(to_load.length) {
|
||||
loaded = $.when(
|
||||
loaded,
|
||||
self.rpc('/web/webclient/csslist', {mods: to_load}).done(self.do_load_css),
|
||||
self.rpc('/web/webclient/qweblist', {mods: to_load}).then(self.do_load_qweb),
|
||||
self.rpc('/web/webclient/csslist', {mods: to_load}).done(self.load_css.bind(self)),
|
||||
self.rpc('/web/webclient/qweblist', {mods: to_load}).then(self.load_qweb.bind(self)),
|
||||
self.rpc('/web/webclient/jslist', {mods: to_load}).done(function(files) {
|
||||
file_list = file_list.concat(files);
|
||||
})
|
||||
);
|
||||
}
|
||||
return loaded.then(function () {
|
||||
return self.do_load_js(file_list);
|
||||
return self.load_js(file_list);
|
||||
}).done(function() {
|
||||
self.on_modules_loaded();
|
||||
self.trigger('module_loaded');
|
||||
|
@ -190,7 +190,7 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
});
|
||||
});
|
||||
},
|
||||
do_load_css: function (files) {
|
||||
load_css: function (files) {
|
||||
var self = this;
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
|
@ -200,7 +200,7 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
}));
|
||||
});
|
||||
},
|
||||
do_load_js: function(files) {
|
||||
load_js: function(files) {
|
||||
var self = this;
|
||||
var d = $.Deferred();
|
||||
if(files.length != 0) {
|
||||
|
@ -212,7 +212,7 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files).done(function () {
|
||||
self.load_js(files).done(function () {
|
||||
d.resolve();
|
||||
});
|
||||
};
|
||||
|
@ -223,7 +223,7 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
}
|
||||
return d;
|
||||
},
|
||||
do_load_qweb: function(files) {
|
||||
load_qweb: function(files) {
|
||||
var self = this;
|
||||
_.each(files, function(file) {
|
||||
self.qweb_mutex.exec(function() {
|
||||
|
|
|
@ -358,17 +358,15 @@ instance.web.Model = instance.web.Class.extend({
|
|||
},
|
||||
});
|
||||
|
||||
instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
||||
instance.web.DataSet = instance.web.Class.extend({
|
||||
/**
|
||||
* Collection of OpenERP records, used to share records and the current selection between views.
|
||||
*
|
||||
* @constructs instance.web.DataSet
|
||||
* @extends instance.web.CallbackEnabled
|
||||
*
|
||||
* @param {String} model the OpenERP model this dataset will manage
|
||||
*/
|
||||
init: function(parent, model, context) {
|
||||
this._super(parent);
|
||||
this.model = model;
|
||||
this.context = context || {};
|
||||
this.index = null;
|
||||
|
|
|
@ -1557,9 +1557,8 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
|
|||
}
|
||||
});
|
||||
|
||||
var DataGroup = instance.web.CallbackEnabled.extend({
|
||||
var DataGroup = instance.web.Class.extend({
|
||||
init: function(parent, model, domain, context, group_by, level) {
|
||||
this._super(parent, null);
|
||||
this.model = new instance.web.Model(model, context, domain);
|
||||
this.group_by = group_by;
|
||||
this.context = context;
|
||||
|
|
Loading…
Reference in New Issue