[IMP] web: float_factor and float_toggle widgets

This commit provides new js widgets for list, kanban and form
views on float field.

1/ 'float_factor' displays the normal float field, but takes a
conversion factor as option. The displays value is the normal
one multiplied by the factor.

You can use the widget like
<field name="my_float_field" widget="float_factor"
option="{'factor': 2}"/>

2/ 'float_toggle' displays a button (in edit mode) looping on a
range of given value at each click. A conversion factor is optional
(default will be 1) to display a converted value, but sent to
non converted one to the server.

You can use the widget like
<field name="my_float" widget="float_toggle"
option="{'range': [0, 0.5, 1], 'factor': 2}"/>

'range' and 'factor' are put in the options.
In simple read mode, the widget display the value as a traditionnal
text (like a normal char field).

This commit provides tests and documentation for those 2 widgets.

Task #39079
This commit is contained in:
jem-odoo
2018-08-13 14:33:48 +02:00
parent 6b4062ea63
commit 1f72644c44
7 changed files with 299 additions and 1 deletions
+139 -1
View File
@@ -898,6 +898,142 @@ var FieldFloatTime = FieldFloat.extend({
formatType: 'float_time',
});
var FieldFloatFactor = FieldFloat.extend({
supportedFieldTypes: ['float'],
className: 'o_field_float_factor',
formatType: 'float_factor',
/**
* @constructor
*/
init: function () {
this._super.apply(this, arguments);
// default values
if (!this.nodeOptions.factor){
this.nodeOptions.factor = 1;
}
// use as format and parse options
this.parseOptions = this.nodeOptions;
}
});
/**
* The goal of this widget is to replace the input field by a button containing a
* range of possible values (given in the options). Each click allows the user to loop
* in the range. The purpose here is to restrict the field value to a predefined selection.
* Also, the widget support the factor conversion as the *float_factor* widget (Range values
* should be the result of the conversion).
**/
var FieldFloatToggle = AbstractField.extend({
supportedFieldTypes: ['float'],
formatType: 'float_factor',
className: 'o_field_float_toggle',
tagName: 'span',
events: {
click: '_onClick'
},
/**
* @constructor
*/
init: function () {
this._super.apply(this, arguments);
this.formatType = 'float_factor';
if (this.mode === 'edit') {
this.tagName = 'button';
}
// we don't inherit Float Field
if (this.attrs.digits) {
this.nodeOptions.digits = JSON.parse(this.attrs.digits);
}
// default values
if (!this.nodeOptions.factor){
this.nodeOptions.factor = 1;
}
if (!this.nodeOptions.range){
this.nodeOptions.range = [0.0, 0.5, 1.0];
}
// use as format and parse options
this.parseOptions = this.nodeOptions;
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Get the display value but in real type to use it in calculations
*
* @private
* @returns {float} The current formatted value
*/
_getDisplayedValue: function () {
return parseFloat(this._formatValue(this.value));
},
/**
* Formats the HTML input tag for edit mode and stores selection status.
*
* @override
* @private
*/
_renderEdit: function () {
// Keep a reference to the input so $el can become something else
// without losing track of the actual input.
this.$el.text(this._formatValue(this.value));
},
/**
* Resets the content to the formated value in readonly mode.
*
* @override
* @private
*/
_renderReadonly: function () {
this.$el.text(this._formatValue(this.value));
},
/**
* Get the next value in the range, from the current one. If the current
* one is not in the range, the next value of the closest one will be chosen.
*
* @private
* @returns {number} The next formatted value in the range
*/
_nextValue: function () {
var range = this.nodeOptions.range;
var val = utils.closestNumber(this._getDisplayedValue(), range);
var index = _.indexOf(range, val);
if (index !== -1) {
if (index + 1 < range.length) {
return range[index + 1];
}
}
return range[0];
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* Clicking on the button triggers the change of value; the next one of
* the range will be displayed.
*
* @private
* @param {OdooEvent} ev
*/
_onClick: function(ev) {
if (this.mode === 'edit') {
ev.stopPropagation(); // only stop propagation in edit mode
var next_val = this._nextValue();
this._setValue(next_val.toString()); // will be parsed in _setValue
}
},
});
var FieldPercentage = FieldFloat.extend({
formatType:'percentage',
});
@@ -1102,7 +1238,7 @@ var CopyClipboard = {
$clipboardBtn.tooltip({title: _t('Copied !'), trigger: 'manual', placement: 'right'});
this.clipboard = new ClipboardJS($clipboardBtn[0], {
text: function (_) {
return self.value.trim();
return self.value.trim();
},
// Container added because of Bootstrap modal that give the focus to another element.
// We need to give to correct focus to ClipboardJS (see in ClipboardJS doc)
@@ -2757,6 +2893,8 @@ return {
FieldDomain: FieldDomain,
FieldFloat: FieldFloat,
FieldFloatTime: FieldFloatTime,
FieldFloatFactor: FieldFloatFactor,
FieldFloatToggle: FieldFloatToggle,
FieldPercentage : FieldPercentage,
FieldInteger: FieldInteger,
FieldMonetary: FieldMonetary,