summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2017-04-19 18:06:12 +0200
committerqsm-odoo <qsm@odoo.com>2017-05-04 12:07:30 +0200
commit250e716c3a12e88acb4a199b427dc47d4ec55d5d (patch)
tree0be849fd0af8d54f556af5f1274e641200ec82ef /addons/web/static/src/js
parent8943aae665ea906aa03bc30cada884c571738b7c (diff)
[REF] web, *: restore views design
Since the new views merge, a lot of design elements were broken. This was particularly impacting the fields in the editable list view; indeed the editable list view is not using an inline form view anymore so the fields in the list were not properly styled as the LESS was still defined assuming the form view environment (for example the invalid fields were red for o2m fields in form view but not in editable list view even though they got the right CSS class). This commit refactor the LESS following these rules: - No more division of non-layout and layout rules. Dividing LESS rules in x_layout.less and x.less was a mistake. Many rules can be considered to be layout and not layout at the same time, developers always have to switch from one file part to the other, many CSS selectors (and rules!) are duplicated for nothing, ... - Field style is extracted from x_view.less and put in the new fields.less file. As before, the fields_extra.less will contain the rules specific to community so that the enterprise repo can override those by replacing the whole file. - Many classes have been renamed so that o_form_x_y becomes o_x_y as many classes can now be applied outside of form view. These classes should not be used in templates anyway. The commit also changes the DOM of fields so that it is more minimalist (no useless parent div, etc). Input elements are not automatically styled anymore, they have to get the o_input class explicitely. This allows to fix lots of small style bugs of previous versions (required monetary field had not the proper style, readonly m2m tags appeared as editable, ...). This also improves the LESS code. The editable list view should also completely stop flickering on chrome and firefox. The commit also removes the orange outline on list view dirty cells. The commit also removes deprecated static xml, LESS and other code. Notice there are still styles to restore/fix and LESS to improve.
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/core/dom.js41
-rw-r--r--addons/web/static/src/js/fields/abstract_field.js2
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js105
-rw-r--r--addons/web/static/src/js/fields/field_registry.js2
-rw-r--r--addons/web/static/src/js/fields/field_utils.js19
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js37
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js18
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js45
-rw-r--r--addons/web/static/src/js/views/list/list_editable_renderer.js54
-rw-r--r--addons/web/static/src/js/widgets/switch_company_menu.js4
10 files changed, 143 insertions, 184 deletions
diff --git a/addons/web/static/src/js/core/dom.js b/addons/web/static/src/js/core/dom.js
index 4333061f924..2dad9eb912f 100644
--- a/addons/web/static/src/js/core/dom.js
+++ b/addons/web/static/src/js/core/dom.js
@@ -56,7 +56,12 @@ return {
if ($textarea.data("auto_resize")) {
return;
}
- function resize () {
+
+ var $fixedTextarea;
+ var minHeight;
+
+ function resize() {
+ $fixedTextarea.insertAfter($textarea);
var heightOffset;
var style = window.getComputedStyle($textarea[0], null);
if (style.boxSizing === 'content-box') {
@@ -64,28 +69,25 @@ return {
} else {
heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
}
- $fixed_text_area.width($textarea.width());
- $fixed_text_area.val($textarea.val());
- var height = $fixed_text_area[0].scrollHeight;
- $textarea.css({height: Math.max(height + heightOffset, min_height)});
+ $fixedTextarea.width($textarea.width());
+ $fixedTextarea.val($textarea.val());
+ var height = $fixedTextarea[0].scrollHeight;
+ $textarea.css({height: Math.max(height + heightOffset, minHeight)});
}
options = options || {};
+ minHeight = (options && options.min_height) || 50;
- var $fixed_text_area;
- var min_height = (options && options.min_height) || 50;
- if (!$fixed_text_area) {
- $fixed_text_area = $('<textarea disabled>').css({
- position: 'absolute',
- opacity: 0,
- height: 10,
- top: -10000,
- left: -10000,
- });
- $fixed_text_area.addClass($textarea[0].className);
- $fixed_text_area.insertAfter($textarea);
- $fixed_text_area.data("auto_resize", true);
- }
+ $fixedTextarea = $('<textarea disabled>', {
+ class: $textarea[0].className,
+ }).css({
+ position: 'absolute',
+ opacity: 0,
+ height: 10,
+ top: -10000,
+ left: -10000,
+ });
+ $fixedTextarea.data("auto_resize", true);
var style = window.getComputedStyle($textarea[0], null);
if (style.resize === 'vertical') {
@@ -101,7 +103,6 @@ return {
core.bus.on('DOM_updated', options.parent, resize);
core.bus.on('view_shown', options.parent, resize);
}
-
},
/**
* Detaches widgets from the DOM and performs their on_detach_callback()
diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js
index 4948a3e3c31..dd2caaa5dd1 100644
--- a/addons/web/static/src/js/fields/abstract_field.js
+++ b/addons/web/static/src/js/fields/abstract_field.js
@@ -34,7 +34,6 @@ var field_utils = require('web.field_utils');
var Widget = require('web.Widget');
var AbstractField = Widget.extend({
- className: 'o_field_widget',
events: {
'keydown': '_onKeydown',
},
@@ -151,6 +150,7 @@ var AbstractField = Widget.extend({
var self = this;
return this._super.apply(this, arguments).then(function () {
self.$el.attr('name', self.name);
+ self.$el.addClass('o_field_widget');
return self._render();
});
},
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index e600954b967..7b48574fb44 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -184,7 +184,7 @@ var InputField = DebouncedField.extend({
*/
_prepareInput: function ($input) {
this.$input = $input || $("<input/>");
- this.$input.addClass('o_form_input');
+ this.$input.addClass('o_input');
this.$input.attr({
type: 'text',
placeholder: this.attrs.placeholder || "",
@@ -261,12 +261,13 @@ var InputField = DebouncedField.extend({
});
var FieldChar = InputField.extend({
- supportedFieldTypes: ['char'],
+ className: 'o_field_char',
tagName: 'span',
+ supportedFieldTypes: ['char'],
});
var FieldDate = InputField.extend({
- className: "o_form_field_date",
+ className: "o_field_date",
tagName: "span",
supportedFieldTypes: ['date'],
@@ -411,7 +412,8 @@ var FieldDateTime = FieldDate.extend({
});
var FieldMonetary = InputField.extend({
- className: 'o_form_field_monetary o_list_number',
+ className: 'o_field_monetary o_field_number',
+ tagName: 'span',
supportedFieldTypes: ['float', 'monetary'],
resetOnAnyFieldChange: true, // Have to listen to currency changes
@@ -436,6 +438,7 @@ var FieldMonetary = InputField.extend({
if (this.mode === 'edit' && this.currency) {
this.tagName = 'div';
+ this.className += ' o_input';
}
},
@@ -554,28 +557,18 @@ var FieldBoolean = AbstractField.extend({
/**
* The actual checkbox is designed in css to have full control over its
* appearance, as opposed to letting the browser and the os decide how
- * a checkbox should look. The actual input is disabled and hidden.
+ * a checkbox should look. The actual input is disabled and hidden. In
+ * readonly mode, the checkbox is disabled.
*
* @override
* @private
*/
- _renderReadonly: function () {
+ _render: function () {
var $checkbox = this._formatValue(this.value);
this.$input = $checkbox.find('input');
- this.$el.empty().append($checkbox);
- },
-
- /**
- * The actual checkbox is designed in css to have full control over its
- * appearance, as opposed to letting the browser and the os decide how
- * a checkbox should look. The actual input is hidden.
- *
- * @override
- * @private
- */
- _renderEdit: function () {
- this._renderReadonly();
- this.$input.prop('disabled', false);
+ this.$input.prop('disabled', this.mode === 'readonly');
+ this.$el.addClass($checkbox.attr('class'));
+ this.$el.empty().append($checkbox.contents());
},
//--------------------------------------------------------------------------
@@ -591,7 +584,6 @@ var FieldBoolean = AbstractField.extend({
_onChange: function () {
this._setValue(this.$input[0].checked);
},
-
/**
* Implement keyboard movements. Mostly useful for its environment, such
* as a list view.
@@ -624,6 +616,8 @@ var FieldBoolean = AbstractField.extend({
});
var FieldInteger = InputField.extend({
+ className: 'o_field_integer o_field_number',
+ tagName: 'span',
supportedFieldTypes: ['integer'],
//--------------------------------------------------------------------------
@@ -669,6 +663,8 @@ var FieldInteger = InputField.extend({
});
var FieldFloat = InputField.extend({
+ className: 'o_field_float o_field_number',
+ tagName: 'span',
supportedFieldTypes: ['float'],
/**
@@ -696,22 +692,6 @@ var FieldFloat = InputField.extend({
isSet: function () {
return this.value === 0 || this._super.apply(this, arguments);
},
-
- //--------------------------------------------------------------------------
- // Private
- //--------------------------------------------------------------------------
-
- /**
- * Format value according to precision parameter.
- *
- * @override
- * @private
- */
- _renderReadonly: function () {
- var value = this._formatValue(this.value);
- var $span = $('<span>').addClass('o_form_field o_form_field_number').text(value);
- this.$el.html($span);
- },
});
var FieldFloatTime = FieldFloat.extend({
@@ -743,21 +723,28 @@ var FieldFloatTime = FieldFloat.extend({
});
var FieldText = DebouncedField.extend({
+ className: 'o_field_text',
supportedFieldTypes: ['text'],
/**
- * In edit mode, the text widget contains a textarea. We append it in
- * start() instead of _renderEdit() to keep the same textarea even
- * if several _renderEdit are done. This allows to keep the cursor
- * position and to autoresize only once.
+ * @constructor
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+
+ if (this.mode === 'edit') {
+ this.tagName = 'textarea';
+ this.className += ' o_input';
+ }
+ },
+ /**
+ * As it it done in the start function, the autoresize is done only once.
*
* @override
*/
start: function () {
- this.$el.addClass('o_list_text o_form_textarea');
-
if (this.mode === 'edit') {
- this.$textarea = $('<textarea>').appendTo(this.$el);
+ this.$textarea = this.$el;
if (this.attrs.placeholder) {
this.$textarea.attr('placeholder', this.attrs.placeholder);
}
@@ -816,13 +803,14 @@ var FieldText = DebouncedField.extend({
* Displays a handle to modify the sequence.
*/
var HandleWidget = AbstractField.extend({
- tagName: 'span',
className: 'o_row_handle fa fa-arrows ui-sortable-handle',
+ tagName: 'span',
description: "",
supportedFieldTypes: ['integer'],
});
-var EmailWidget = InputField.extend({
+var FieldEmail = InputField.extend({
+ className: 'o_field_email',
prefix: 'mailto',
supportedFieldTypes: ['char'],
@@ -853,7 +841,8 @@ var EmailWidget = InputField.extend({
}
});
-var FieldPhone = EmailWidget.extend({
+var FieldPhone = FieldEmail.extend({
+ className: 'o_field_phone',
prefix: 'tel',
/**
@@ -907,6 +896,7 @@ var FieldPhone = EmailWidget.extend({
});
var UrlWidget = InputField.extend({
+ className: 'o_field_url',
supportedFieldTypes: ['char'],
/**
@@ -939,9 +929,9 @@ var UrlWidget = InputField.extend({
var AbstractFieldBinary = AbstractField.extend({
events: _.extend({}, AbstractField.prototype.events, {
- 'change .o_form_input_file': 'on_file_change',
+ 'change .o_input_file': 'on_file_change',
'click .o_select_file_button': function () {
- this.$('.o_form_input_file').click();
+ this.$('.o_input_file').click();
},
'click .o_clear_file_button': 'on_clear',
}),
@@ -1084,8 +1074,8 @@ var FieldBinaryFile = AbstractFieldBinary.extend({
this.on_save_as(event);
}
},
- 'click .o_form_input': function () { // eq[0]
- this.$('.o_form_input_file').click();
+ 'click .o_input': function () { // eq[0]
+ this.$('.o_input_file').click();
},
}),
supportedFieldTypes: ['binary'],
@@ -1106,7 +1096,7 @@ var FieldBinaryFile = AbstractFieldBinary.extend({
if (this.value) {
this.$el.children().removeClass('o_hidden');
this.$('.o_select_file_button').first().addClass('o_hidden');
- this.$('.o_form_input').eq(0).val(this.filename_value || this.value);
+ this.$('.o_input').eq(0).val(this.filename_value || this.value);
} else {
this.$el.children().addClass('o_hidden');
this.$('.o_select_file_button').first().removeClass('o_hidden');
@@ -1727,8 +1717,8 @@ var FieldToggleBoolean = AbstractField.extend({
* @private
*/
_render: function () {
- var class_name = this.value ? 'o_toggle_button_success' : 'text-muted';
- this.$('i').attr('class', ('fa fa-circle ' + class_name));
+ var className = this.value ? 'o_toggle_button_success' : 'text-muted';
+ this.$('i').addClass('fa fa-circle ' + className);
var title = this.value ? this.attrs.options.active : this.attrs.options.inactive;
this.$el.attr('title', title);
},
@@ -1747,7 +1737,6 @@ var FieldToggleBoolean = AbstractField.extend({
event.stopPropagation();
this._setValue(!this.value);
},
-
});
var JournalDashboardGraph = AbstractField.extend({
@@ -1891,7 +1880,7 @@ var FieldDomain = AbstractField.extend({
events: _.extend({}, AbstractField.prototype.events, {
"click .o_domain_show_selection_button": "_onShowSelectionButtonClick",
- "click .o_form_field_domain_dialog_button": "_onDialogEditButtonClick",
+ "click .o_field_domain_dialog_button": "_onDialogEditButtonClick",
}),
custom_events: {
"domain_changed": "_onDomainSelectorValueChange",
@@ -1907,7 +1896,7 @@ var FieldDomain = AbstractField.extend({
this.inDialog = !!this.nodeOptions.in_dialog;
this.fsFilters = this.nodeOptions.fs_filters || {};
- this.className = "o_form_field_domain";
+ this.className = "o_field_domain";
if (this.mode === "edit") {
this.className += " o_edit_mode";
}
@@ -2190,7 +2179,7 @@ var AceEditor = DebouncedField.extend({
return {
DebouncedField: DebouncedField,
- EmailWidget: EmailWidget,
+ FieldEmail: FieldEmail,
FieldBinaryFile: FieldBinaryFile,
FieldBinaryImage: FieldBinaryImage,
FieldBoolean: FieldBoolean,
diff --git a/addons/web/static/src/js/fields/field_registry.js b/addons/web/static/src/js/fields/field_registry.js
index 41889fcfa85..dcd8f7acd48 100644
--- a/addons/web/static/src/js/fields/field_registry.js
+++ b/addons/web/static/src/js/fields/field_registry.js
@@ -29,7 +29,7 @@ registry
.add('float', basic_fields.FieldFloat)
.add('char', basic_fields.FieldChar)
.add('handle', basic_fields.HandleWidget)
- .add('email', basic_fields.EmailWidget)
+ .add('email', basic_fields.FieldEmail)
.add('phone', basic_fields.FieldPhone)
.add('url', basic_fields.UrlWidget)
.add('image', basic_fields.FieldBinaryImage)
diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js
index afc15b7a882..508d97b131c 100644
--- a/addons/web/static/src/js/fields/field_utils.js
+++ b/addons/web/static/src/js/fields/field_utils.js
@@ -35,13 +35,16 @@ var _t = core._t;
* @returns {jQueryElement}
*/
function formatBoolean(value) {
- var $input = $('<input type="checkbox">')
- .prop('checked', value)
- .prop('disabled', true);
- return $('<div>')
- .addClass('o_checkbox')
- .append($input)
- .append($('<span>'));
+ var $input = $('<input/>', {
+ type: 'checkbox',
+ }).prop({
+ checked: value,
+ disabled: true,
+ });
+ var $div = $('<div/>', {
+ class: 'o_checkbox',
+ });
+ return $div.append($input, '<span/>');
}
/**
@@ -342,7 +345,7 @@ function parseDateTime(value, field, options) {
var pattern2 = datePatternWoZero + ' ' + timePatternWoZero;
var datetime;
if (options && options.isUTC) {
- // phatomjs crash if we don't use this format
+ // phatomjs crash if we don't use this format
datetime = moment.utc(value.replace(' ', 'T') + 'Z');
} else {
datetime = moment.utc(value, [pattern1, pattern2, moment.ISO_8601], true);
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index 28d790b16c4..d7e65f5c4bf 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -81,9 +81,9 @@ var FieldMany2One = AbstractField.extend({
'search_create_popup': '_onSearchCreatePopup',
},
events: _.extend({}, AbstractField.prototype.events, {
- 'click .o_form_input': '_onInputClick',
- 'focusout .o_form_input': '_onInputFocusout',
- 'keyup .o_form_input': '_onInputKeyup',
+ 'click input': '_onInputClick',
+ 'focusout input': '_onInputFocusout',
+ 'keyup input': '_onInputKeyup',
'click .o_external_button': '_onExternalButtonClick',
'click': '_onClick',
}),
@@ -106,7 +106,7 @@ var FieldMany2One = AbstractField.extend({
// what is 'this.floating' for? add a comment!
this.floating = false;
- this.$input = this.$('.o_form_input');
+ this.$input = this.$('input');
this.$external_button = this.$('.o_external_button');
return this._super.apply(this, arguments);
},
@@ -713,7 +713,7 @@ var FieldX2Many = AbstractField.extend({
onFailure: def.reject.bind(def),
});
} else {
- self.renderer.setRowMode(recordID, 'readonly', true);
+ self.renderer.setRowMode(recordID, 'readonly');
def.resolve();
}
});
@@ -819,7 +819,7 @@ var FieldX2Many = AbstractField.extend({
});
var FieldOne2Many = FieldX2Many.extend({
- className: 'o_form_field_one2many',
+ className: 'o_field_one2many',
supportedFieldTypes: ['one2many'],
//--------------------------------------------------------------------------
@@ -937,7 +937,7 @@ var FieldOne2Many = FieldX2Many.extend({
});
var FieldMany2Many = FieldX2Many.extend({
- className: 'o_form_field_many2many',
+ className: 'o_field_many2many',
supportedFieldTypes: ['many2many'],
/**
@@ -1019,7 +1019,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({
events: {
'click .o_attach': '_onAttach',
'click .oe_delete': '_onDelete',
- 'change .o_form_input_file': '_onFileChanged',
+ 'change .o_input_file': '_onFileChanged',
},
/**
* @constructor
@@ -1102,7 +1102,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({
_onAttach: function () {
// This widget uses a hidden form to upload files. Clicking on 'Attach'
// will simulate a click on the related input.
- this.$('.o_form_input_file').click();
+ this.$('.o_input_file').click();
},
/**
* @private
@@ -1196,7 +1196,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({
var FieldMany2ManyTags = AbstractField.extend({
tag_template: "FieldMany2ManyTag",
- className: "o_form_field o_form_field_many2manytags",
+ className: "o_field_many2manytags",
supportedFieldTypes: ['many2many'],
custom_events: {
field_changed: '_onFieldChanged',
@@ -1204,13 +1204,24 @@ var FieldMany2ManyTags = AbstractField.extend({
},
events: _.extend({}, AbstractField.prototype.events, {
'click .o_delete': '_onDeleteTag',
- 'keydown .o_form_field_many2one input': '_onKeyDown',
+ 'keydown .o_field_many2one input': '_onKeyDown',
}),
fieldsToFetch: {
color: {type: 'integer'},
display_name: {type: 'char'},
},
+ /**
+ * @constructor
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+
+ if (this.mode === 'edit') {
+ this.className += ' o_input';
+ }
+ },
+
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
@@ -1310,7 +1321,7 @@ var FieldMany2ManyTags = AbstractField.extend({
this.many2one._getSearchBlacklist = function () {
return self.value.res_ids;
};
- this.many2one.appendTo(this.$el);
+ return this.many2one.appendTo(this.$el);
},
/**
* @private
@@ -1445,7 +1456,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
var KanbanFieldMany2ManyTags = FieldMany2ManyTags.extend({
_render: function () {
var self = this;
- this.$el.addClass('o_form_field_many2manytags o_kanban_tags');
+ this.$el.addClass('o_field_many2manytags o_kanban_tags');
_.each(this.value.data, function (m2m) {
// 10th color is invisible
if ('color' in m2m.data && m2m.data.color !== 10) {
diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js
index e150b0b2dd0..25ba02530be 100644
--- a/addons/web/static/src/js/views/basic/basic_renderer.js
+++ b/addons/web/static/src/js/views/basic/basic_renderer.js
@@ -52,7 +52,7 @@ var BasicRenderer = AbstractRenderer.extend({
if (!canBeSaved) {
invalidFields.push(widget.name);
}
- widget.$el.toggleClass('o_form_invalid', !canBeSaved);
+ widget.$el.toggleClass('o_field_invalid', !canBeSaved);
});
return invalidFields;
},
@@ -249,9 +249,9 @@ var BasicRenderer = AbstractRenderer.extend({
}
// Toggle modifiers CSS classes if necessary
- element.$el.toggleClass("o_form_invisible", !!modifiers.invisible);
- element.$el.toggleClass("o_readonly", !!modifiers.readonly);
- element.$el.toggleClass("o_form_required", !!modifiers.required);
+ element.$el.toggleClass("o_invisible_modifier", !!modifiers.invisible);
+ element.$el.toggleClass("o_readonly_modifier", !!modifiers.readonly);
+ element.$el.toggleClass("o_required_modifier", !!modifiers.required);
// Call associated callback
if (element.callback) {
@@ -495,7 +495,15 @@ var BasicRenderer = AbstractRenderer.extend({
// Update the modifiers registration by associating the widget and by
// giving the modifiers options now (as the potential callback is
// associated to new widget)
- this._registerModifiers(node, record, widget, modifiersOptions);
+ this._registerModifiers(node, record, widget, _.extend({
+ callback: (function (element, modifiers, record) {
+ element.$el.toggleClass('o_field_empty', !!(
+ record.data.id
+ && (modifiers.readonly || this.mode === 'readonly')
+ && !element.widget.isSet()
+ ));
+ }).bind(this),
+ }, modifiersOptions || {}));
return widget;
},
diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js
index 20244f12e95..f6bcbd49eeb 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -8,10 +8,6 @@ var core = require('web.core');
var _t = core._t;
var qweb = core.qweb;
-var FIELD_CLASSES = {
- 'one2many': 'o_field_one2many',
-};
-
var FormRenderer = BasicRenderer.extend({
className: "o_form_view",
/**
@@ -27,7 +23,7 @@ var FormRenderer = BasicRenderer.extend({
//--------------------------------------------------------------------------
/**
- * Extend the method so that labels also receive the 'o_form_invalid' class
+ * Extend the method so that labels also receive the 'o_field_invalid' class
* if necessary.
*
* @override
@@ -40,14 +36,14 @@ var FormRenderer = BasicRenderer.extend({
var fieldNames = this._super.apply(this, arguments);
var $labels = this.$('label');
- $labels.removeClass('o_form_invalid');
+ $labels.removeClass('o_field_invalid');
_.each(fieldNames, function (fieldName) {
var idForLabel = self.idsForLabels[fieldName];
if (idForLabel) {
$labels
.filter('[for=' + idForLabel + ']')
- .addClass('o_form_invalid');
+ .addClass('o_field_invalid');
}
});
return fieldNames;
@@ -66,7 +62,7 @@ var FormRenderer = BasicRenderer.extend({
_.each(resetWidgets, function (widget) {
self._setIDForLabel(widget, self.idsForLabels[widget.name]);
});
- return resetWidgets
+ return resetWidgets;
});
},
/**
@@ -105,7 +101,7 @@ var FormRenderer = BasicRenderer.extend({
var name = $notebook.data('name');
if (name in state) {
var $page = $notebook.find('> ul > li').eq(state[name]);
- if (!$page.hasClass('o_form_invisible')) {
+ if (!$page.hasClass('o_invisible_modifier')) {
$page.find('a[data-toggle="tab"]').click();
}
}
@@ -138,15 +134,6 @@ var FormRenderer = BasicRenderer.extend({
//--------------------------------------------------------------------------
/**
- * Adds the adequate classnames to a field widget's $el.
- *
- * @private
- * @param {Object} widget a field widget
- */
- _addFieldClassNames: function (widget) {
- widget.$el.addClass('o_form_field'); // TODO will be removed in the CSS update
- },
- /**
* @private
* @param {jQueryElement} $el
* @param {Object} node
@@ -207,7 +194,7 @@ var FormRenderer = BasicRenderer.extend({
}
});
var buttons_partition = _.partition(buttons, function ($button) {
- return $button.is('.o_form_invisible');
+ return $button.is('.o_invisible_modifier');
});
var invisible_buttons = buttons_partition[0];
var visible_buttons = buttons_partition[1];
@@ -261,22 +248,8 @@ var FormRenderer = BasicRenderer.extend({
* @returns {AbstractField}
*/
_renderFieldWidget: function (node, record, options, modifiersOptions) {
- var self = this;
- modifiersOptions = _.extend({
- callback: function (element, modifiers, record) {
- element.$el.toggleClass('o_form_field_empty', !!( // FIXME condition is evaluated twice (label AND widget...)
- record.data.id
- && (modifiers.readonly || self.mode === 'readonly')
- && !element.widget.isSet()
- ));
- },
- }, modifiersOptions || {});
-
- var widget = this._super(node, record, options, modifiersOptions);
+ var widget = this._super.apply(this, arguments);
this._setIDForLabel(widget, this._getIDForLabel(node.attrs.name));
-
- widget.$el.addClass(FIELD_CLASSES[record.fields[node.attrs.name].type]);
- this._addFieldClassNames(widget);
this._handleAttributes(widget.$el, node);
if (JSON.parse(node.attrs.default_focus || "0")) {
this.defaultFocusField = widget;
@@ -344,7 +317,7 @@ var FormRenderer = BasicRenderer.extend({
});
this._registerModifiers(node, this.state, $label, {
callback: function (element, modifiers, record) {
- element.$el.toggleClass('o_form_label_empty', !!(
+ element.$el.toggleClass('o_form_label_empty', !!( // FIXME condition is evaluated twice (label AND widget...)
record.data.id
&& (modifiers.readonly || self.mode === 'readonly')
&& !widget.isSet() // getting like this because it could have been re-rendered...
@@ -656,7 +629,7 @@ var FormRenderer = BasicRenderer.extend({
if (modifiers.invisible && element.$el.hasClass('active')) {
element.$el.removeClass('active');
tab.$page.removeClass('active');
- var $firstVisibleTab = $headers.find('li:not(.o_form_invisible):first()');
+ var $firstVisibleTab = $headers.find('li:not(.o_invisible_modifier):first()');
$firstVisibleTab.addClass('active');
$pages.find($firstVisibleTab.find('a').attr('href')).addClass('active');
}
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 3d34b80f846..1b662fa46af 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
@@ -29,7 +29,7 @@ ListRenderer.include({
'click tbody tr:not(.o_data_row)': '_onEmptyRowClick',
'click tfoot': '_onFooterClick',
'click tr .o_list_record_delete': '_onTrashIconClick',
- 'click .o_form_field_x2many_list_row_add a': '_onAddRecord',
+ 'click .o_field_x2many_list_row_add a': '_onAddRecord',
}),
/**
* @override
@@ -90,31 +90,6 @@ ListRenderer.include({
return this._super(recordID);
},
/**
- * @see BasicRenderer.confirmChange
- *
- * We also react to changes by adding the 'o_field_dirty' css class,
- * which changes its style to a visible orange outline. It allows the user
- * to have a visual feedback on which fields changed, and on which fields
- * have been saved.
- *
- * @todo maybe should be a basic behavior
- *
- * @override
- * @param {Object} state - a record resource (the new full state)
- * @param {string} id - the local id for the changed record
- * @param {string[]} fields - list of modified fields
- * @param {OdooEvent} e - the event that triggered the change
- * @returns {Deferred}
- */
- confirmChange: function (state, id, fields, e) {
- return this._super.apply(this, arguments).then(function (resetWidgets) {
- _.each(resetWidgets, function (widget) {
- var $td = widget.$el.parent();
- $td.addClass('o_field_dirty');
- });
- });
- },
- /**
* This method is called by the controller when the user has clicked 'save',
* and the model as actually saved the current changes. We then need to
* set the correct values for each cell. The difference with confirmChange
@@ -172,9 +147,8 @@ ListRenderer.include({
*
* @param {string} recordID
* @param {string} mode
- * @param {boolean} [keepDirtyFlag=false]
*/
- setRowMode: function (recordID, mode, keepDirtyFlag) {
+ setRowMode: function (recordID, mode) {
var self = this;
var rowIndex = _.findIndex(this.state.data, {id: recordID});
if (rowIndex < 0) {
@@ -185,12 +159,18 @@ ListRenderer.include({
this.currentRow = editMode ? rowIndex : null;
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');
+ // Force the size of each cell to its current value so that it
+ // won't change if its content changes, to prevent the view from
+ // flickering
+ $tds.each(function () {
+ var $td = $(this);
+ $td.css({width: $td.outerWidth()});
+ });
_.each(this.columns, function (node, colIndex) {
var $td = $tds.eq(colIndex);
var $newTd = self._renderBodyCell(record, node, colIndex, {
@@ -203,18 +183,16 @@ ListRenderer.include({
self._unregisterModifiersElement(node, record, $td.children());
}
- // Force the width of each cell to its current value so that it
- // won't change if its content changes, to prevent the view from
- // flickering
- $td.width($td.width());
$td.empty().append($newTd.contents());
});
_.each(oldWidgets, this._destroyFieldWidget.bind(this, record));
} else {
for (var colIndex = 0; colIndex < this.columns.length; colIndex++) {
- this._setCellValue(rowIndex, colIndex, keepDirtyFlag || false);
+ this._setCellValue(rowIndex, colIndex);
}
}
+
+ $row.toggleClass('o_selected_row', editMode); // Toggle here so that style is applied at the end
},
//--------------------------------------------------------------------------
@@ -310,7 +288,7 @@ ListRenderer.include({
var $a = $('<a href="#">').text(_t("Add an item"));
var $td = $('<td>')
.attr('colspan', this._getNumberOfCols())
- .addClass('o_form_field_x2many_list_row_add')
+ .addClass('o_field_x2many_list_row_add')
.append($a);
var $tr = $('<tr>').append($td);
$rows.push($tr);
@@ -398,17 +376,13 @@ ListRenderer.include({
*
* @param {integer} rowIndex
* @param {integer} colIndex
- * @param {boolean} keepDirtyFlag
*/
- _setCellValue: function (rowIndex, colIndex, keepDirtyFlag) {
+ _setCellValue: function (rowIndex, colIndex) {
var record = this.state.data[rowIndex];
var node = this.columns[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');
- }
this._unregisterModifiersElement(node, record, $oldTd);
$oldTd.replaceWith($newTd);
diff --git a/addons/web/static/src/js/widgets/switch_company_menu.js b/addons/web/static/src/js/widgets/switch_company_menu.js
index 8bea91a5a97..c27a6d82603 100644
--- a/addons/web/static/src/js/widgets/switch_company_menu.js
+++ b/addons/web/static/src/js/widgets/switch_company_menu.js
@@ -34,9 +34,9 @@ var SwitchCompanyMenu = Widget.extend({
_.each(session.user_companies.allowed_companies, function(company) {
var a = '';
if (company[0] === session.user_companies.current_company[0]) {
- a = '<i class="fa fa-check o_current_company"></i>';
+ a = '<i class="fa fa-check mr8"></i>';
} else {
- a = '<span class="o_company"/>';
+ a = '<span class="mr24"/>';
}
companies_list += '<li><a href="#" data-menu="company" data-company-id="' + company[0] + '">' + a + company[1] + '</a></li>';
});