diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js
index f9468418b9b..a9b9cacd9c9 100644
--- a/addons/web/static/src/js/views/list/list_editable_renderer.js
+++ b/addons/web/static/src/js/views/list/list_editable_renderer.js
@@ -25,7 +25,7 @@ ListRenderer.include({
move_next_line: '_onMoveNextLine',
}),
events: _.extend({}, ListRenderer.prototype.events, {
- 'click tbody td': '_onCellClick',
+ 'click tbody td.o_data_cell': '_onCellClick',
'click tbody tr:not(.o_data_row)': '_onEmptyRowClick',
'click tfoot': '_onFooterClick',
'click tr .o_list_record_delete': '_onTrashIconClick',
@@ -161,8 +161,8 @@ ListRenderer.include({
if (rowIndex === this.currentRow) {
this.currentRow = null;
}
- var $row = this.$('tbody > tr:nth(' + rowIndex + ')');
- $row.remove(); // FIXME row indexes are not updated... let's remove data('index') and check index dynamically ?
+ var $row = this.$('.o_data_row:nth(' + rowIndex + ')');
+ $row.remove();
this.state = state;
},
@@ -184,14 +184,15 @@ ListRenderer.include({
var record = this.state.data[rowIndex];
this.currentRow = editMode ? rowIndex : null;
- var $row = this.$('tbody > tr:nth(' + rowIndex + ')');
+ var $row = this.$('.o_data_row:nth(' + rowIndex + ')');
$row.toggleClass('o_selected_row', editMode);
if (editMode) {
// Instantiate column widgets and destroy potential readonly ones
var oldWidgets = _.clone(this.allFieldWidgets[record.id]);
+ var $tds = $row.children('.o_data_cell');
_.each(this.columns, function (node, colIndex) {
- var $td = self._findTd($row, colIndex);
+ var $td = $tds.eq(colIndex);
var $newTd = self._renderBodyCell(record, node, colIndex, {
renderInvisible: true,
renderWidgets: true,
@@ -220,18 +221,6 @@ ListRenderer.include({
// Private
//--------------------------------------------------------------------------
- /**
- * Find the td in a row corresponding the a field with a given index. The
- * main problem is that in some cases, we have a 'selector' checkbox, so the
- * correct td is sometimes at position i, sometimes at i+1
- *
- * @param {jQueryElement} $row the $tr for the row we are interested in
- * @param {number} index the index of the field/column
- * @returns {jQueryElement} the $td for the index-th field
- */
- _findTd: function ($row, index) {
- return $row.children(':nth(' + (index + (this.hasSelectors ? 1 : 0)) + ')');
- },
/**
* Returns the current number of columns. The editable renderer may add a
* trash icon on the right of a record, so we need to take this into account
@@ -291,27 +280,8 @@ ListRenderer.include({
return $body;
},
/**
- * Add all the necessary styling classes to displayed cells. Also, we need
- * to add the current index to each cell data attribute, so we can get it
- * back when we need to select a cell.
- *
- * @override
- * @param {Object} record
- * @param {Object} node
- * @param {integer} index
- * @param {Object} [options]
- * @returns {jQueryElement}
- */
- _renderBodyCell: function (record, node, index, options) {
- var $cell = this._super.apply(this, arguments);
- if (this.mode === 'readonly') {
- return $cell;
- }
- return $cell.data('index', index);
- },
- /**
- * Editable rows are extended with their index, and possibly a trash icon on
- * their right, to allow deleting the corresponding record.
+ * Editable rows are possibly extended with a trash icon on their right, to
+ * allow deleting the corresponding record.
*
* @override
* @param {any} record
@@ -320,12 +290,9 @@ ListRenderer.include({
*/
_renderRow: function (record, index) {
var $row = this._super.apply(this, arguments);
- if (this.mode === 'edit') {
- $row.data('index', index);
- }
if (this.addTrashIcon) {
- var $icon = $('').addClass('fa fa-trash-o').attr('name', 'delete');
- var $td = $('
').addClass('o_list_record_delete').append($icon);
+ var $icon = $('', {class: 'fa fa-trash-o', name: 'delete'});
+ var $td = $(' | ', {class: 'o_list_record_delete'}).append($icon);
$row.append($td);
}
return $row;
@@ -432,7 +399,7 @@ ListRenderer.include({
var record = this.state.data[rowIndex];
var node = this.columns[colIndex];
- var $oldTd = this._findTd(this.$('tbody > tr:nth(' + rowIndex + ')'), colIndex);
+ var $oldTd = this.$('.o_data_row:nth(' + rowIndex + ') > .o_data_cell:nth(' + colIndex + ')');
var $newTd = this._renderBodyCell(record, node, colIndex, {mode: 'readonly'});
if (keepDirtyFlag && $oldTd.hasClass('o_field_dirty')) {
$newTd.addClass('o_field_dirty');
@@ -515,11 +482,10 @@ ListRenderer.include({
return;
}
var $td = $(event.currentTarget);
- var rowIndex = $td.parent().data('index');
- var colIndex = $td.data('index');
- if (colIndex !== undefined && rowIndex !== undefined) {
- this._selectCell(rowIndex, colIndex);
- }
+ var $tr = $td.parent();
+ var rowIndex = this.$('.o_data_row').index($tr);
+ var colIndex = $tr.find('.o_data_cell').index($td);
+ this._selectCell(rowIndex, colIndex);
},
/**
* We need to manually unselect row, because noone else would do it
diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js
index c788ca0d44b..2305530affe 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -260,15 +260,17 @@ var ListRenderer = BasicRenderer.extend({
* @returns {jQueryElement} a | element
*/
_renderBodyCell: function (record, node, colIndex, options) {
- var tdClassName;
+ var tdClassName = 'o_data_cell';
if (node.tag === 'button') {
- tdClassName = 'o_list_button';
- } else if (node.attrs.widget){
- tdClassName = ('o_' + node.attrs.widget + '_cell');
+ tdClassName += ' o_list_button';
} else {
- tdClassName = FIELD_CLASSES[this.state.fields[node.attrs.name].type];
+ if (node.attrs.widget){
+ tdClassName += (' o_' + node.attrs.widget + '_cell');
+ } else {
+ tdClassName += (' ' + FIELD_CLASSES[this.state.fields[node.attrs.name].type]);
+ }
}
- var $td = $(' | ', { class: tdClassName });
+ var $td = $(' | ', {class: tdClassName});
// We register modifiers on the | element so that it gets the correct
// modifiers classes (for styling)
@@ -550,14 +552,17 @@ var ListRenderer = BasicRenderer.extend({
* @returns {jQueryElement} a | element
*/
_renderRow: function (record) {
- var decorations = this._computeDecorationClassNames(record);
var self = this;
var $cells = _.map(this.columns, function (node, index) {
return self._renderBodyCell(record, node, index, {mode: 'readonly'});
});
- var $tr = $('
')
+ var className = 'o_data_row';
+ var decorations = this._computeDecorationClassNames(record);
+ if (decorations.length) {
+ className += (' ' + decorations.join(' '));
+ }
+ var $tr = $('
', {class: className})
.data('id', record.id)
- .addClass(decorations.length && decorations.join(' '))
.append($cells);
if (this.hasSelectors) {
$tr.prepend(this._renderSelector('td'));
diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js
index 9ad2f10e631..4a8c87be598 100644
--- a/addons/web/static/tests/views/list_tests.js
+++ b/addons/web/static/tests/views/list_tests.js
@@ -1693,6 +1693,34 @@ QUnit.module('Views', {
list.destroy();
});
+ QUnit.test('edit list line after line deletion', function (assert) {
+ assert.expect(5);
+
+ var list = createView({
+ View: ListView,
+ model: 'foo',
+ data: this.data,
+ arch: '',
+ });
+
+ list.$('.o_data_row:nth(2) > td:not(.o_list_record_selector)').first().click();
+ assert.ok(list.$('.o_data_row:nth(2)').is('.o_selected_row'),
+ "third row should be in edition");
+ list.$buttons.find('.o_list_button_discard').click();
+ list.$buttons.find('.o_list_button_add').click();
+ assert.ok(list.$('.o_data_row:nth(0)').is('.o_selected_row'),
+ "first row should be in edition (creation)");
+ list.$buttons.find('.o_list_button_discard').click();
+ assert.strictEqual(list.$('.o_selected_row').length, 0,
+ "no row should be selected");
+ list.$('.o_data_row:nth(2) > td:not(.o_list_record_selector)').first().click();
+ assert.ok(list.$('.o_data_row:nth(2)').is('.o_selected_row'),
+ "third row should be in edition");
+ assert.strictEqual(list.$('.o_selected_row').length, 1,
+ "no other row should be selected");
+
+ list.destroy();
+ });
});
});