From 3fe19453475e33f17f79fa47148e109295dae98c Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sat, 10 Nov 2012 20:00:14 +0100 Subject: use ES5 bind() for better stack traces bzr revid: al@openerp.com-20121110190014-ead1981ez6up6ri1 --- addons/web/static/src/js/corelib.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'addons/web/static/src/js/corelib.js') diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index d2e94d37939..f2fb1bb2141 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -429,17 +429,11 @@ 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]); + this[name] = this[name].bind(this); } } } -- cgit v1.2.3 From 27c872cef382ab18532b55fd675fb1e6f316d568 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sat, 10 Nov 2012 20:34:40 +0100 Subject: remove CallbackEnabled The on_/do_ binding still happens in Widget.init, but as we now use ES5 bind() it doesnt clutter stack traces anymore. However the fate of this automatic binding feature remains uncertain. bzr revid: al@openerp.com-20121110193440-78mpwamqx7iwq2ux --- addons/web/static/src/js/corelib.js | 104 ++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 59 deletions(-) (limited to 'addons/web/static/src/js/corelib.js') diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index f2fb1bb2141..dab06b374e9 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -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,60 +427,28 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, { } }); -instance.web.CallbackEnabledMixin = _.extend({}, instance.web.PropertiesMixin, { - init: function() { - instance.web.PropertiesMixin.init.call(this); - // Transform on_/do_* methods into callbacks - for (var name in this) { - if(typeof(this[name]) == "function") { - if((/^on_|^do_/).test(name)) { - this[name] = this[name].bind(this); - } - } - } - }, - /** - * 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); - } - } -}); - -instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { +instance.web.WidgetMixin = _.extend({},instance.web.PropertiesMixin, { /** * 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); + } + } + } }, /** * Destroys the current widget, also destroys all its children before destroying itself. @@ -568,17 +537,36 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { */ start: function() { return $.when(); + }, + /** + * 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.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. @@ -645,7 +633,6 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { * 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 @@ -935,7 +922,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', @@ -944,13 +931,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); }, -- cgit v1.2.3 From 2e810433c9a144434319051784cc1038623536d2 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sat, 10 Nov 2012 20:46:54 +0100 Subject: remove WidgetMixin bzr revid: al@openerp.com-20121110194654-0q10uajsy6nmzzd6 --- addons/web/static/src/js/corelib.js | 149 ++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 82 deletions(-) (limited to 'addons/web/static/src/js/corelib.js') diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index dab06b374e9..4012be526e6 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -427,7 +427,70 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, { } }); -instance.web.WidgetMixin = _.extend({},instance.web.PropertiesMixin, { +// Classes + +/** + * 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. * @@ -449,6 +512,9 @@ instance.web.WidgetMixin = _.extend({},instance.web.PropertiesMixin, { } } } + // 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. @@ -563,86 +629,6 @@ instance.web.WidgetMixin = _.extend({},instance.web.PropertiesMixin, { var fn = (typeof method === 'string') ? self[method] : method; return fn.apply(self, arguments); } - } -}); - -// Classes -/** - * 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. - * - * @type string - */ - template: null, - /** - * Constructs the widget and sets its parent if a parent is given. - * - * @constructs instance.web.Widget - * - * @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; }, /** * Renders the element. The default implementation renders the widget using QWeb, @@ -659,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. -- cgit v1.2.3 From e1f5dfc388b1a5d8269b74cbde6b6f599a44f9ef Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Wed, 14 Nov 2012 12:33:35 +0100 Subject: [FIX] jsonp wasn't working on some browse due to security restriction that do not store the third parties cookies. bzr revid: chs@openerp.com-20121114113335-nag3ljcwwx0yfdnu --- addons/web/static/src/js/corelib.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'addons/web/static/src/js/corelib.js') diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 4012be526e6..5c4ef8b5cbb 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -1309,8 +1309,17 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { // extracted from payload to set on the url var data = { session_id: this.session_id, - id: payload.id + id: payload.id, + sid: this.httpsessionid, }; + + var set_sid = function (response, textStatus, jqXHR) { + // If response give us the http session id, we store it for next requests... + if (response.httpsessionid) { + self.httpsessionid = response.httpsessionid; + } + }; + url.url = this.get_url(url.url); var ajax = _.extend({ type: "GET", @@ -1326,7 +1335,7 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { if(payload_url.length < 2000) { // Direct jsonp request ajax.data.r = payload_str; - return $.ajax(ajax); + return $.ajax(ajax).done(set_sid); } else { // Indirect jsonp request var ifid = _.uniqueId('oe_rpc_iframe'); @@ -1364,7 +1373,7 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { }); // append the iframe to the DOM (will trigger the first load) $form.after($iframe); - return deferred; + return deferred.done(set_sid); } }, get_url: function (file) { -- cgit v1.2.3 From 67115184f8cadd7d1185c1aaa4c8f654909d058c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 14 Nov 2012 14:06:00 +0100 Subject: [FIX] references to renamed/removed methods in event handler bindings bzr revid: xmo@openerp.com-20121114130600-2qf8egm0r9bwno1n --- addons/web/static/src/js/corelib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web/static/src/js/corelib.js') diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 5c4ef8b5cbb..879cf94dcdd 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -1276,7 +1276,7 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { }; deferred.reject(error, $.Event()); }); - // Allow deferred user to disable on_rpc_error in fail + // Allow deferred user to disable rpc_error call in fail deferred.fail(function() { deferred.fail(function(error, event) { if (!event.isDefaultPrevented()) { -- cgit v1.2.3 From eb5a5bf838fdeac8564802f3b08fbfad6066e8e7 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Wed, 14 Nov 2012 18:41:50 +0100 Subject: [IMP] add method session.url() to generate correct url bzr revid: chs@openerp.com-20121114174150-9nhj50vftt4lrf0k --- addons/web/static/src/js/corelib.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'addons/web/static/src/js/corelib.js') diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 879cf94dcdd..6ea0fd53372 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -1320,7 +1320,7 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { } }; - url.url = this.get_url(url.url); + url.url = this.url(url.url, null); var ajax = _.extend({ type: "GET", dataType: 'jsonp', @@ -1376,8 +1376,17 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { return deferred.done(set_sid); } }, - get_url: function (file) { - return this.prefix + file; + + url: function(path, params) { + var qs = ''; + if (!_.isNull(params)) { + params = _.extend(params || {}, {session_id: this.session_id}); + if (this.httpsessionid) { + params.sid = this.httpsessionid; + } + qs = '?' + $.param(params); + } + return this.prefix + path + qs; }, }); -- cgit v1.2.3 From 76cce62c999514b493919f843f5bd45024bb5c1d Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Fri, 16 Nov 2012 10:42:00 +0100 Subject: [IMP] Added feature in the rpc() method to be able to perform a call without triggering the loading messages. bzr revid: nicolas.vanhoren@openerp.com-20121116094200-q4cby6jofcrk87hd --- addons/web/static/src/js/corelib.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'addons/web/static/src/js/corelib.js') diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 6ea0fd53372..06b3940f1e1 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -774,10 +774,10 @@ instance.web.Widget = instance.web.Class.extend(instance.web.PropertiesMixin, { } return false; }, - rpc: function(url, data, success, error) { - var def = $.Deferred().done(success).fail(error); + rpc: function(url, data, options) { + var def = $.Deferred(); var self = this; - instance.session.rpc(url, data).done(function() { + instance.session.rpc(url, data, options).done(function() { if (!self.isDestroyed()) def.resolve.apply(def, arguments); }).fail(function() { @@ -1231,12 +1231,14 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { * * @param {String} url RPC endpoint * @param {Object} params call parameters + * @param {Object} options additional options for rpc call * @param {Function} success_callback function to execute on RPC call success * @param {Function} error_callback function to execute on RPC call failure * @returns {jQuery.Deferred} jquery-provided ajax deferred */ - rpc: function(url, params) { + rpc: function(url, params, options) { var self = this; + options = options || {}; // url can be an $.ajax option object if (_.isString(url)) { url = { url: url }; @@ -1251,10 +1253,12 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { id: _.uniqueId('r') }; var deferred = $.Deferred(); - this.trigger('request', url, payload); + if (! options.shadow) + this.trigger('request', url, payload); var request = this.rpc_function(url, payload).done( function (response, textStatus, jqXHR) { - self.trigger('response', response); + if (! options.shadow) + self.trigger('response', response); if (!response.error) { if (url.url === '/web/session/eval_domain_and_context') { self.test_eval(params, response.result); @@ -1268,7 +1272,8 @@ instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, { } ).fail( function(jqXHR, textStatus, errorThrown) { - self.trigger('response_failed', jqXHR); + if (! options.shadow) + self.trigger('response_failed', jqXHR); var error = { code: -32098, message: "XmlHttpRequestError " + errorThrown, -- cgit v1.2.3