diff options
| author | Christophe Simonis <chs@odoo.com> | 2017-06-27 14:19:31 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2017-06-27 14:19:31 +0200 |
| commit | dd43071638773dcb58376b79ec7b1456c8b0454d (patch) | |
| tree | fd7935e2aa93de03fa3fe12507f8ef74405a255e /addons/web/static/src/js/fields | |
| parent | 6501184e6294ffb06e24a0ec8e9666b79a80b59a (diff) | |
| parent | 278e478d55209bd958836fde7fe1c82c555180dc (diff) | |
[MERGE] forward port branch saas-16 up to 278e478d552
Diffstat (limited to 'addons/web/static/src/js/fields')
| -rw-r--r-- | addons/web/static/src/js/fields/abstract_field.js | 30 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/basic_fields.js | 149 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/relational_fields.js | 22 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/upgrade_fields.js | 6 |
4 files changed, 120 insertions, 87 deletions
diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js index 492d9f26552..52e0aef77e4 100644 --- a/addons/web/static/src/js/fields/abstract_field.js +++ b/addons/web/static/src/js/fields/abstract_field.js @@ -142,6 +142,21 @@ var AbstractField = Widget.extend({ // this is the last value that was set by the user, unparsed. This is // used to avoid setting the value twice in a row with the exact value. this.lastSetValue = undefined; + + // formatType is used to determine which format (and parse) functions + // to call to format the field's value to insert into the DOM (typically + // put into a span or an input), and to parse the value from the input + // to send it to the server. These functions are chosen according to + // the 'widget' attrs if is is given, and if it is a valid key, with a + // fallback on the field type, ensuring that the value is formatted and + // displayed according to the choosen widget, if any. + this.formatType = this.attrs.widget in field_utils.format ? + this.attrs.widget : + this.field.type; + // formatOptions (resp. parseOptions) is a dict of options passed to + // calls to the format (resp. parse) function. + this.formatOptions = {}; + this.parseOptions = {}; }, /** * When a field widget is appended to the DOM, its start method is called, @@ -266,15 +281,15 @@ var AbstractField = Widget.extend({ //-------------------------------------------------------------------------- /** - * convert the value from the field to a string representation + * Converts the value from the field to a string representation. * * @private * @param {any} value (from the field type) * @returns {string} */ _formatValue: function (value) { - var options = _.extend({}, this.nodeOptions, { data: this.recordData }); - return field_utils.format[this.field.type](value, this.field, options); + var options = _.extend({}, this.nodeOptions, { data: this.recordData }, this.formatOptions); + return field_utils.format[this.formatType](value, this.field, options); }, /** * This method check if a value is the same as the current value of the @@ -291,15 +306,14 @@ var AbstractField = Widget.extend({ return this.value === value; }, /** - * convert a string representation to a valid value, depending on the field - * type. + * Converts a string representation to a valid value. * * @private * @param {string} value * @returns {any} */ _parseValue: function (value) { - return field_utils.parse[this.field.type](value, this.field); + return field_utils.parse[this.formatType](value, this.field, this.parseOptions); }, /** * main rendering function. Override this if your widget has the same render @@ -426,22 +440,18 @@ var AbstractField = Widget.extend({ this.trigger_up('navigation_move', {direction: 'cancel'}); break; case $.ui.keyCode.UP: - ev.preventDefault(); ev.stopPropagation(); this.trigger_up('navigation_move', {direction: 'up'}); break; case $.ui.keyCode.RIGHT: - ev.preventDefault(); ev.stopPropagation(); this.trigger_up('navigation_move', {direction: 'right'}); break; case $.ui.keyCode.DOWN: - ev.preventDefault(); ev.stopPropagation(); this.trigger_up('navigation_move', {direction: 'down'}); break; case $.ui.keyCode.LEFT: - ev.preventDefault(); ev.stopPropagation(); this.trigger_up('navigation_move', {direction: 'left'}); break; diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index d4013a8bcdb..82970255b3e 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -285,11 +285,15 @@ var InputField = DebouncedField.extend({ */ _onNavigationMove: function (ev) { this._super.apply(this, arguments); - var input = this.$input[0]; - var selecting = (input.selectionEnd !== input.selectionStart); - if ((ev.data.direction === "left" && (selecting || input.selectionStart !== 0)) - || (ev.data.direction === "right" && (selecting || input.selectionStart !== input.value.length))) { - ev.stopPropagation(); + + // the following code only makes sense in edit mode, with an input + if (this.mode === 'edit') { + var input = this.$input[0]; + var selecting = (input.selectionEnd !== input.selectionStart); + if ((ev.data.direction === "left" && (selecting || input.selectionStart !== 0)) + || (ev.data.direction === "right" && (selecting || input.selectionStart !== input.value.length))) { + ev.stopPropagation(); + } } }, }); @@ -322,6 +326,14 @@ var FieldDate = InputField.extend({ supportedFieldTypes: ['date'], /** + * @override + */ + init: function () { + this._super.apply(this, arguments); + // use the session timezone when formatting dates + this.formatOptions.timezone = true; + }, + /** * In edit mode, instantiates a DateWidget datepicker and listen to changes. * * @override @@ -396,17 +408,6 @@ var FieldDate = InputField.extend({ this.datewidget.setValue(this.value); this.$input = this.datewidget.$input; }, - - /** - * FieldDateTime overrides _formatValue to use the session timezone - * - * @override - * @private - * @param {Moment} value - */ - _formatValue: function (value) { - return field_utils.format.date(value, {timezone: true}); - }, }); var FieldDateTime = FieldDate.extend({ @@ -448,17 +449,6 @@ var FieldDateTime = FieldDate.extend({ this.datewidget.setValue(value); this.$input = this.datewidget.$input; }, - - /** - * FieldDateTime overrides _formatValue to use the session timezone - * - * @override - * @private - * @param {Moment} value - */ - _formatValue: function (value) { - return field_utils.format.datetime(value, {timezone: true}); - }, }); var FieldMonetary = InputField.extend({ @@ -490,6 +480,13 @@ var FieldMonetary = InputField.extend({ this.tagName = 'div'; this.className += ' o_input'; } + + // use the formatFloat function in edit + if (this.mode === 'edit') { + this.formatType = 'float'; + } + this.formatOptions.currency = this.currency; + this.formatOptions.digits = [16, 2]; }, //-------------------------------------------------------------------------- @@ -562,22 +559,6 @@ var FieldMonetary = InputField.extend({ var currencyID = this.record.data[currencyField] && this.record.data[currencyField].res_id; this.currency = session.get_currency(currencyID); }, - /** - * FieldMonetary overrides _formatValue to use the format monetary method - * in readonly. - * - * @override - * @private - * @param {float} value - * @returns {string} - */ - _formatValue: function (value) { - var format = field_utils.format[this.mode === 'edit' ? "float" : "monetary"]; - return format(value, this.field, { - digits: [16, 2], - currency: this.currency, - }); - }, }); var FieldBoolean = AbstractField.extend({ @@ -686,6 +667,11 @@ var FieldBoolean = AbstractField.extend({ this.$input.prop('checked', !this.value); this._setValue(!this.value); return; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + ev.preventDefault(); } this._super.apply(this, arguments); }, @@ -734,7 +720,7 @@ var FieldInteger = InputField.extend({ } return value; } - return field_utils.format.integer(value, this.field); + return this._super.apply(this, arguments); }, }); @@ -771,31 +757,11 @@ var FieldFloat = InputField.extend({ }); var FieldFloatTime = FieldFloat.extend({ - supportedFieldTypes: ['float'], - - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - - /** - * Format the float time value into a human-readable time format. - * - * @override - * @private - */ - _formatValue: function (value) { - return field_utils.format.float_time(value); - }, - - /** - * Parse the human-readable formatted time value into a float. - * - * @override - * @private - */ - _parseValue: function (value) { - return field_utils.parse.float_time(value); - }, + // this is not strictly necessary, as for this widget to be used, the 'widget' + // attrs must be set to 'float_time', so the formatType is automatically + // 'float_time', but for the sake of clarity, we explicitely define a + // FieldFloatTime widget with formatType = 'float_time'. + formatType: 'float_time', }); var FieldText = InputField.extend(TranslatableFieldMixin, { @@ -853,6 +819,19 @@ var FieldEmail = InputField.extend({ }, //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Returns the associated link. + * + * @override + */ + getFocusableElement: function () { + return this.mode === 'readonly' ? this.$el : this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- @@ -887,6 +866,17 @@ var FieldPhone = FieldEmail.extend({ this.tagName = 'span'; } }, + /** + * Returns the associated link only if there is one. + * + * @override + */ + getFocusableElement: function () { + if (this._canCall()) { + return this._super.apply(this, arguments); + } + return $(); + }, //-------------------------------------------------------------------------- // Private @@ -941,6 +931,19 @@ var UrlWidget = InputField.extend({ }, //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Returns the associated link. + * + * @override + */ + getFocusableElement: function () { + return this.mode === 'readonly' ? this.$el : this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- @@ -1041,7 +1044,13 @@ var AbstractFieldBinary = AbstractField.extend({ set_filename: function (value) { var filename = this.attrs.filename; if (filename && filename in this.fields) { - this.trigger_up('update_field', { name: filename, value: value }); + var changes = {}; + changes[filename] = value; + this.trigger_up('field_changed', { + dataPointID: this.dataPointID, + changes: changes, + viewType: this.viewType, + }); } }, on_clear: function () { diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 3b47b8c64b0..419d1f5f646 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -124,7 +124,7 @@ var FieldMany2One = AbstractField.extend({ * @returns {jQuery} */ getFocusableElement: function () { - return this.$input || $(); + return this.mode === 'edit' && this.$input || this.$el; }, /** * TODO @@ -206,6 +206,17 @@ var FieldMany2One = AbstractField.extend({ return []; }, /** + * Returns the display_name from a string which contains it but was altered + * as a result of the show_address option using a horrible hack. + * + * @private + * @param {string} value + * @returns {string} display_name without show_address mess + */ + _getDisplayName: function (value) { + return value.split('\n')[0]; + }, + /** * @private * @param {string} name */ @@ -244,7 +255,7 @@ var FieldMany2One = AbstractField.extend({ // and hope for the best that noone tries to uses this mechanism to do // something else. if (this.nodeOptions.always_reload) { - value = value.split('\n')[0]; + value = this._getDisplayName(value); } this.$input.val(value); if (!this.autocomplete_bound) { @@ -302,7 +313,7 @@ var FieldMany2One = AbstractField.extend({ .then(function (result) { // possible selections for the m2o var values = _.map(result, function (x) { - x[1] = x[1].split("\n")[0]; + x[1] = self._getDisplayName(x[1]); return { label: _.str.escapeHTML(x[1].trim()) || data.noDisplayContent, value: x[1], @@ -478,7 +489,7 @@ var FieldMany2One = AbstractField.extend({ _onInputKeyup: function () { if (this.$input.val() === "") { this.reinitialize(false); - } else if (this.m2o_value !== this.$input.val()) { + } else if (this._getDisplayName(this.m2o_value) !== this.$input.val()) { this.floating = true; this._updateExternalButton(); } @@ -1585,7 +1596,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({ var KanbanFieldMany2ManyTags = FieldMany2ManyTags.extend({ _render: function () { var self = this; - this.$el.addClass('o_field_many2manytags o_kanban_tags'); + this.$el.empty().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) { @@ -1763,6 +1774,7 @@ var FieldSelection = AbstractField.extend({ this._super.apply(this, arguments); if (this.field.type === 'many2one') { this.values = this.record.specialData[this.name]; + this.formatType = 'many2one'; } else { this.values = _.reject(this.field.selection, function (v) { return v[0] === false && v[1] === ''; diff --git a/addons/web/static/src/js/fields/upgrade_fields.js b/addons/web/static/src/js/fields/upgrade_fields.js index ecf267e03c1..ae8cae56ef3 100644 --- a/addons/web/static/src/js/fields/upgrade_fields.js +++ b/addons/web/static/src/js/fields/upgrade_fields.js @@ -6,6 +6,7 @@ odoo.define('web.upgrade_widgets', function (require) { * When checked, an upgrade popup is showed to the user. */ +var AbstractField = require('web.AbstractField'); var basic_fields = require('web.basic_fields'); var core = require('web.core'); var Dialog = require('web.Dialog'); @@ -58,6 +59,7 @@ var AbstractFieldUpgrade = { * Opens the Upgrade dialog. * * @private + * @returns {Dialog} the instance of the opened Dialog */ _openDialog: function () { var message = $(QWeb.render('EnterpriseUpgrade')); @@ -75,7 +77,7 @@ var AbstractFieldUpgrade = { }, ]; - new Dialog(this, { + return new Dialog(this, { size: 'medium', buttons: buttons, $content: $('<div>', { @@ -122,7 +124,7 @@ var AbstractFieldUpgrade = { var UpgradeBoolean = FieldBoolean.extend(AbstractFieldUpgrade, { supportedFieldTypes: [], - events: _.extend({}, FieldBoolean.prototype.events, { + events: _.extend({}, AbstractField.prototype.events, { 'click input': '_onInputClicked', }), |
