[IMP] add lazier proxy method on CallbackEnabled, use it in WebClient and ListView
authorXavier Morel <xmo@openerp.com>
Thu, 12 Jan 2012 08:49:10 +0000 (09:49 +0100)
committerXavier Morel <xmo@openerp.com>
Thu, 12 Jan 2012 08:49:10 +0000 (09:49 +0100)
bzr revid: xmo@openerp.com-20120112084910-6fxbzbgmv51utyko

addons/web/static/src/js/chrome.js
addons/web/static/src/js/core.js
addons/web/static/src/js/view_list.js
addons/web/static/src/js/view_list_editable.js

index 85a7c9f..39ddd0e 100644 (file)
@@ -1102,11 +1102,11 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
         self.$table = $(QWeb.render("Interface", {}));
         self.$element.append(self.$table);
         self.header = new openerp.web.Header(self);
-        self.header.on_logout.add(self.on_logout);
-        self.header.on_action.add(self.on_menu_action);
+        self.header.on_logout.add(this.proxy('on_logout'));
+        self.header.on_action.add(this.proxy('on_menu_action'));
         self.header.appendTo($("#oe_header"));
         self.menu = new openerp.web.Menu(self, "oe_menu", "oe_secondary_menu");
-        self.menu.on_action.add(self.on_menu_action);
+        self.menu.on_action.add(this.proxy('on_menu_action'));
         self.menu.start();
     },
     show_common: function() {
index a194c34..d5c096d 100644 (file)
@@ -348,6 +348,31 @@ openerp.web.CallbackEnabled = openerp.web.Class.extend(/** @lends openerp.web.Ca
                 }
             }
         }
+    },
+    /**
+     * 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} method_name name of the method to invoke
+     * @returns {Function} proxied method
+     */
+    proxy: function (method_name) {
+        var self = this;
+        return function () {
+            return self[method_name].apply(self, arguments);
+        }
     }
 });
 
index 63f9dfd..e654b77 100644 (file)
@@ -217,11 +217,11 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
         });
 
         this.$element.find('.oe-list-add')
-                .click(this.do_add_record)
+                .click(this.proxy('do_add_record'))
                 .attr('disabled', grouped && this.options.editable);
         this.$element.find('.oe-list-delete')
                 .attr('disabled', true)
-                .click(this.do_delete_selected);
+                .click(this.proxy('do_delete_selected'));
         this.$element.find('thead').delegate('th.oe-sortable[data-id]', 'click', function (e) {
             e.stopPropagation();
 
@@ -512,7 +512,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
         this.no_leaf = !!context['group_by_no_leaf'];
 
         this.reload_view(!!group_by, context).then(
-            $.proxy(this, 'reload_content'));
+            this.proxy('reload_content'));
     },
     /**
      * Handles the signal to delete lines from the records list
@@ -795,7 +795,7 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
                 $row.remove();
                 self.refresh_zebra(index);
             },
-            'reset': $.proxy(this, 'on_records_reset'),
+            'reset': function () { return self.on_records_reset(); },
             'change': function (event, record) {
                 var $row = self.$current.find('[data-id=' + record.get('id') + ']');
                 $row.replaceWith(self.render_record(record));
@@ -917,13 +917,15 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
         });
     },
     render: function () {
+        var self = this;
         if (this.$current) {
             this.$current.remove();
         }
         this.$current = this.$_element.clone(true);
         this.$current.empty().append(
             QWeb.render('ListView.rows', _.extend({
-                render_cell: $.proxy(this, 'render_cell')}, this)));
+                    render_cell: function () { return self.render_cell(); }
+                }, this)));
         this.pad_table_to(5);
     },
     pad_table_to: function (count) {
@@ -1038,7 +1040,7 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
             record: record,
             row_parity: (index % 2 === 0) ? 'even' : 'odd',
             view: this.view,
-            render_cell: $.proxy(this, 'render_cell')
+            render_cell: function () { return this.render_cell(); }
         });
     },
     /**
@@ -1092,7 +1094,9 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L
 
         this.page = 0;
 
-        this.records.bind('reset', $.proxy(this, 'on_records_reset'));
+        var self = this;
+        this.records.bind('reset', function () {
+            return self.on_records_reset(); });
     },
     make_fragment: function () {
         return document.createDocumentFragment();
index daf7081..dcbd22f 100644 (file)
@@ -211,7 +211,7 @@ openerp.web.list_editable = function (openerp) {
                     .delegate('button', 'keyup', function (e) {
                         e.stopImmediatePropagation();
                     })
-                    .keyup($.proxy(self, 'on_row_keyup'));
+                    .keyup(function () { return self.on_row_keyup(); });
                 if (row) {
                     $new_row.replaceAll(row);
                 } else if (self.options.editable) {
@@ -359,7 +359,8 @@ openerp.web.list_editable = function (openerp) {
             this.render_row_as_form();
         },
         render_record: function (record) {
-            var index = this.records.indexOf(record);
+            var index = this.records.indexOf(record),
+                 self = this;
             // FIXME: context dict should probably be extracted cleanly
             return QWeb.render('ListView.row', {
                 columns: this.columns,
@@ -367,7 +368,7 @@ openerp.web.list_editable = function (openerp) {
                 record: record,
                 row_parity: (index % 2 === 0) ? 'even' : 'odd',
                 view: this.view,
-                render_cell: $.proxy(this, 'render_cell'),
+                render_cell: function () { return self.render_cell(); },
                 edited: !!this.edition_form
             });
         }