Xavier (Open ERP) has proposed merging 
lp:~openerp-dev/openerp-web/6.1-o2m-nosuck-xmo into lp:openerp-web/6.1.

Requested reviews:
  Xavier (Open ERP) (xmo)

For more details, see:
https://code.launchpad.net/~openerp-dev/openerp-web/6.1-o2m-nosuck-xmo/+merge/110522
-- 
https://code.launchpad.net/~openerp-dev/openerp-web/6.1-o2m-nosuck-xmo/+merge/110522
Your team OpenERP R&D Team is subscribed to branch 
lp:~openerp-dev/openerp-web/6.1-o2m-nosuck-xmo.
=== modified file 'addons/web/static/src/css/base.css'
--- addons/web/static/src/css/base.css	2012-06-07 11:11:49 +0000
+++ addons/web/static/src/css/base.css	2012-06-15 13:15:26 +0000
@@ -1346,6 +1346,9 @@
     display: inline;
     margin: 0 0.5em 0 0;
 }
+.openerp .oe_form_field_one2many .oe-listview .oe-edit-row-save {
+    visibility: hidden;
+}
 
 .openerp .oe_forms .oe-listview th.oe-sortable .ui-icon,
 .openerp .oe_forms .oe-listview th.oe-sortable .ui-icon {

=== modified file 'addons/web/static/src/js/core.js'
--- addons/web/static/src/js/core.js	2012-05-31 13:20:20 +0000
+++ addons/web/static/src/js/core.js	2012-06-15 13:15:26 +0000
@@ -42,7 +42,6 @@
         for (var name in prop) {
             // Check if we're overwriting an existing function
             prototype[name] = typeof prop[name] == "function" &&
-                              typeof _super[name] == "function" &&
                               fnTest.test(prop[name]) ?
                     (function(name, fn) {
                         return function() {

=== modified file 'addons/web/static/src/js/view_form.js'
--- addons/web/static/src/js/view_form.js	2012-06-14 08:40:09 +0000
+++ addons/web/static/src/js/view_form.js	2012-06-15 13:15:26 +0000
@@ -549,7 +549,8 @@
             return $.Deferred().reject();
         } else {
             return $.when(this.reload()).pipe(function () {
-                return $.when(r).then(success); }, null);
+                return r; })
+                    .then(success);
         }
     },
     /**
@@ -583,8 +584,9 @@
                 this.sidebar.attachments.do_update();
             }
             //openerp.log("The record has been created with id #" + this.datarecord.id);
-            this.reload();
-            return $.when(_.extend(r, {created: true})).then(success);
+            return $.when(this.reload()).pipe(function () {
+                return _.extend(r, {created: true}); })
+                    .then(success);
         }
     },
     on_action: function (action) {
@@ -2508,23 +2510,20 @@
 	    }, this));
     },
     is_valid: function() {
-        this.validate();
-        return this._super();
-    },
-    validate: function() {
-        this.invalid = false;
         if (!this.viewmanager.views[this.viewmanager.active_view])
-            return;
+            return true;
         var view = this.viewmanager.views[this.viewmanager.active_view].controller;
-        if (this.viewmanager.active_view === "form") {
-            for (var f in view.fields) {
-                f = view.fields[f];
-                if (!f.is_valid()) {
-                    this.invalid = true;
-                    return;
-                }
-            }
+        switch (this.viewmanager.active_view) {
+        case 'form':
+            return _(view.fields).chain()
+                .invoke('is_valid')
+                .all(_.identity)
+                .value();
+            break;
+        case 'list':
+            return view.is_valid();
         }
+        return true;
     },
     is_dirty: function() {
         this.save_any_view();
@@ -2556,6 +2555,47 @@
 
 openerp.web.form.One2ManyListView = openerp.web.ListView.extend({
     _template: 'One2Many.listview',
+    init: function (parent, dataset, view_id, options) {
+        this._super(parent, dataset, view_id, _.extend(options || {}, {
+            ListType: openerp.web.form.One2ManyList
+        }));
+    },
+    is_valid: function () {
+        var form;
+        // A list not being edited is always valid
+        if (!(form = this.first_edition_form())) {
+            return true;
+        }
+        // If the form has not been modified, the view can only be valid
+        // NB: is_dirty will also be set on defaults/onchanges/whatever?
+        // oe_form_dirty seems to only be set on actual user actions
+        if (!form.$element.is('.oe_form_dirty')) {
+            return true;
+        }
+
+        // Otherwise validate internal form
+        return _(form.fields).chain()
+            .invoke(function () {
+                this.validate();
+                this.update_dom(true);
+                return this.is_valid();
+            })
+            .all(_.identity)
+            .value();
+    },
+    first_edition_form: function () {
+        var get_form = function (group_or_list) {
+            if (group_or_list.edition) {
+                return group_or_list.edition_form;
+            }
+            return _(group_or_list.children).chain()
+                .map(get_form)
+                .compact()
+                .first()
+                .value();
+        };
+        return get_form(this.groups);
+    },
     do_add_record: function () {
         if (this.options.editable) {
             this._super.apply(this, arguments);
@@ -2609,7 +2649,7 @@
             var button_result = self.o2m.dataset.call_button.apply(self.o2m.dataset, arguments);
             self.o2m.reload_current_view();
             return button_result;
-        }
+        };
         pop.on_write.add(function(id, data) {
             self.o2m.dataset.write(id, data, {}, function(r) {
                 self.o2m.reload_current_view();
@@ -2622,6 +2662,39 @@
         return this._super(name, id, _.bind(def.resolve, def));
     }
 });
+openerp.web.form.One2ManyList = openerp.web.ListView.List.extend({
+    render_row_as_form: function () {
+        var self = this;
+        return this._super.apply(this, arguments).then(function () {
+            self.setup_save_on_row_blur();
+        });
+    },
+    bind_blur_focus: function (new_row, onblur, onfocus) {
+        if (new_row.addEventListener) {
+            new_row.addEventListener('blur', onblur, true);
+            new_row.addEventListener('focus', onfocus, true);
+        } else {
+            new_row.onfocusout = onblur;
+            new_row.onfocusin = onfocus;
+        }
+    },
+    setup_save_on_row_blur: function () {
+        var self = this;
+        var form = this.edition_form;
+        this.bind_blur_focus(this.edition_form.$element[0], function () {
+            self._save_row_timeout = setTimeout(function () {
+                if (form.widget_is_stopped) {
+                    // Saved or cancelled already, maybe?
+                    return;
+                }
+                self.view.ensure_saved();
+            }, 0);
+        }, function () {
+            clearTimeout(self._save_row_timeout);
+            delete self._save_row_timeout;
+        });
+    }
+});
 
 openerp.web.form.One2ManyFormView = openerp.web.FormView.extend({
     form_template: 'One2Many.formview',

=== modified file 'addons/web/static/src/js/view_list.js'
--- addons/web/static/src/js/view_list.js	2012-06-06 12:31:15 +0000
+++ addons/web/static/src/js/view_list.js	2012-06-15 13:15:26 +0000
@@ -61,7 +61,7 @@
 
         this.records = new Collection();
 
-        this.set_groups(new openerp.web.ListView.Groups(this));
+        this.set_groups(new (this.options.GroupsType)(this));
 
         if (this.dataset instanceof openerp.web.DataSetStatic) {
             this.groups.datagroup = new openerp.web.StaticDataGroup(this.dataset);
@@ -85,6 +85,14 @@
 
         this.no_leaf = false;
     },
+    set_default_options: function (options) {
+        this._super(options);
+        _.defaults(this.options, {
+            GroupsType: openerp.web.ListView.Groups,
+            ListType: openerp.web.ListView.List
+        });
+    },
+
     /**
      * Retrieves the view's number of records per page (|| section)
      *
@@ -1191,7 +1199,7 @@
                 self.records.proxy(group.value).reset();
                 delete self.children[group.value];
             }
-            var child = self.children[group.value] = new openerp.web.ListView.Groups(self.view, {
+            var child = self.children[group.value] = new (this.view.options.GroupsType)(self.view, {
                 records: self.records.proxy(group.value),
                 options: self.options,
                 columns: self.columns
@@ -1297,7 +1305,7 @@
     },
     render_dataset: function (dataset) {
         var self = this,
-            list = new openerp.web.ListView.List(this, {
+            list = new (this.view.options.ListType)(this, {
                 options: this.options,
                 columns: this.columns,
                 dataset: dataset,

=== modified file 'addons/web/static/src/js/view_list_editable.js'
--- addons/web/static/src/js/view_list_editable.js	2012-05-11 11:15:27 +0000
+++ addons/web/static/src/js/view_list_editable.js	2012-06-15 13:15:26 +0000
@@ -124,29 +124,27 @@
          * Checks if a record is being edited, and if so cancels it
          */
         cancel_pending_edition: function () {
-            var self = this, cancelled = $.Deferred();
+            var self = this, cancelled;
             if (!this.edition) {
-                cancelled.resolve();
-                return cancelled.promise();
+                return $.when();
             }
 
-            if (this.edition_id != null) {
-                this.reload_record(self.records.get(this.edition_id)).then(function () {
-                    cancelled.resolve();
-                });
+            if (this.edition_id) {
+                cancelled = this.reload_record(this.records.get(this.edition_id));
             } else {
-                cancelled.resolve();
+                cancelled = $.when();
             }
             cancelled.then(function () {
                 self.view.unpad_columns();
                 self.edition_form.stop();
                 self.edition_form.$element.remove();
                 delete self.edition_form;
+                self.dataset.index = null;
                 delete self.edition_id;
                 delete self.edition;
             });
             this.pad_table_to(5);
-            return cancelled.promise();
+            return cancelled;
         },
         /**
          * Adapts this list's view description to be suitable to the inner form
@@ -170,24 +168,29 @@
             var self = this;
             switch (e.which) {
             case KEY_RETURN:
-                this.save_row().then(function (result) {
-                    if (result.created) {
-                        self.new_record();
-                        return;
-                    }
+                $(e.target).blur();
+                e.preventDefault();
+                //e.stopImmediatePropagation();
+                setTimeout(function () {
+                    self.save_row().then(function (result) {
+                        if (result.created) {
+                            self.new_record();
+                            return;
+                        }
 
-                    var next_record_id,
-                        next_record = self.records.at(
-                                self.records.indexOf(result.edited_record) + 1);
-                    if (next_record) {
-                        next_record_id = next_record.get('id');
-                        self.dataset.index = _(self.dataset.ids)
-                                .indexOf(next_record_id);
-                    } else {
-                        self.dataset.index = 0;
-                        next_record_id = self.records.at(0).get('id');
-                    }
-                    self.edit_record(next_record_id);
+                        var next_record_id,
+                            next_record = self.records.at(
+                                    self.records.indexOf(result.edited_record) + 1);
+                        if (next_record) {
+                            next_record_id = next_record.get('id');
+                            self.dataset.index = _(self.dataset.ids)
+                                    .indexOf(next_record_id);
+                        } else {
+                            self.dataset.index = 0;
+                            next_record_id = self.records.at(0).get('id');
+                        }
+                        self.edit_record(next_record_id);
+                    }, 0);
                 });
                 break;
             case KEY_ESCAPE:
@@ -197,7 +200,7 @@
         },
         render_row_as_form: function (row) {
             var self = this;
-            this.cancel_pending_edition().then(function () {
+            return this.ensure_saved().pipe(function () {
                 var record_id = $(row).data('id');
                 var $new_row = $('<tr>', {
                         id: _.uniqueId('oe-editable-row-'),
@@ -213,7 +216,13 @@
                     })
                     .keyup(function () {
                         return self.on_row_keyup.apply(self, arguments); })
-                    .keydown(function (e) { e.stopPropagation(); });
+                    .keydown(function (e) { e.stopPropagation(); })
+                    .keypress(function (e) {
+                        if (e.which === KEY_RETURN) {
+                            return false;
+                        }
+                    });
+
                 if (row) {
                     $new_row.replaceAll(row);
                 } else if (self.options.editable) {
@@ -235,6 +244,10 @@
                 }
                 self.edition = true;
                 self.edition_id = record_id;
+                self.dataset.index = _(self.dataset.ids).indexOf(record_id);
+                if (self.dataset.index === -1) {
+                    self.dataset.index = null;
+                }
                 self.edition_form = _.extend(new openerp.web.ListEditableFormView(self.view, self.dataset, false), {
                     form_template: 'ListView.row.form',
                     registry: openerp.web.list.form.widgets,
@@ -242,8 +255,8 @@
                 });
                 // HA HA
                 self.edition_form.appendTo();
-                $.when(self.edition_form.on_loaded(self.get_form_fields_view())).then(function () {
-                    // put in $.when just in case  FormView.on_loaded becomes asynchronous
+                // put in $.when just in case  FormView.on_loaded becomes asynchronous
+                return $.when(self.edition_form.on_loaded(self.get_form_fields_view())).then(function () {
                     $new_row.find('> td')
                           .addClass('oe-field-cell')
                           .removeAttr('width')
@@ -307,7 +320,7 @@
          */
         save_row: function () {
             //noinspection JSPotentiallyInvalidConstructorUsage
-            var self = this, done = $.Deferred();
+            var self = this;
             return this.edition_form
                 .do_save(null, this.options.editable === 'top')
                 .pipe(function (result) {
@@ -327,18 +340,24 @@
                                 created: result.created || false,
                                 edited_record: edited_record
                             };
-                        }, null);
-                }, null);
+                        });
+                });
         },
         /**
          * If the current list is being edited, ensures it's saved
          */
         ensure_saved: function () {
             if (this.edition) {
-                return this.save_row();
+                // kinda-hack-ish: if the user has entered data in a field,
+                // oe_form_dirty will be set on the form so save, otherwise
+                // discard the current (entirely empty) line
+                if (this.edition_form.$element.is('.oe_form_dirty')) {
+                    return this.save_row();
+                }
+                return this.cancel_pending_edition();
             }
             //noinspection JSPotentiallyInvalidConstructorUsage
-            return $.Deferred().resolve().promise();
+            return $.when();
         },
         /**
          * Cancels the edition of the row for the current dataset index
@@ -357,7 +376,6 @@
                 [record_id, this.dataset]);
         },
         new_record: function () {
-            this.dataset.index = null;
             this.render_row_as_form();
         },
         render_record: function (record) {
@@ -405,12 +423,12 @@
                 if (this.modifiers.tree_invisible) {
                     var old_invisible = this.invisible;
                     this.invisible = true;
-                    this._super();
+                    this._super.apply(this, arguments);
                     this.invisible = old_invisible;
                 } else if (this.invisible) {
                     this.$element.children().css('visibility', 'hidden');
                 } else {
-                    this._super();
+                    this._super.apply(this, arguments);
                 }
             }
         });

_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help   : https://help.launchpad.net/ListHelp

Reply via email to