summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/fields/basic_fields.js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2017-03-28 15:58:03 +0200
committerAaron Bohy <aab@odoo.com>2017-04-11 19:44:38 +0200
commitc43a3a5045945658add54a220c02cf0f23c03833 (patch)
tree38dabba7483f517e62631c3bb58c373ad1429ca9 /addons/web/static/src/js/fields/basic_fields.js
parent07f5ac3dabd09dafca261ee596015a50c061a8f8 (diff)
[FIX] web: debounce field changes for input fields
Before this commit, every field changes were sent upstream and triggered a notifyChange, potentially causing multiple (onchanges) RPCS in rapid succession. It is useful to have a feedback of the new values of the fields even without needing to lose the focus, but it should not be done for each keystroke. With this commit, we debounce the onInput handler, so the method setValue is in practice debounced as well. We need to add a handler on the focusout event to make sure that if the user changes input, the setValue is immediately called. Note that we had to add support for that in the test utils environment (and not only in the createView method: field widgets can be instantiated in other environment, such as the reconciliation widget)
Diffstat (limited to 'addons/web/static/src/js/fields/basic_fields.js')
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js63
1 files changed, 33 insertions, 30 deletions
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 4123297f253..136b9cc55df 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -30,6 +30,7 @@ var _t = core._t;
var InputField = AbstractField.extend({
events: _.extend({}, AbstractField.prototype.events, {
'input': '_onInput',
+ 'focusout': '_onFocusout',
}),
/**
@@ -41,6 +42,15 @@ var InputField = AbstractField.extend({
this._super.apply(this, arguments);
if (this.mode === 'edit') {
this.tagName = 'input';
+
+ // we debounce the input changes to make sure they are not done too
+ // quickly. Note that this is done here and not on the prototype,
+ // so each inputfield has its own debounced function to work with.
+ // Also, if the debounce value is set to 0, no debouncing is done,
+ // which is really useful for the unit tests.
+ if (this.DEBOUNCE) {
+ this._onInput = _.debounce(this._onInput.bind(this), this.DEBOUNCE);
+ }
}
},
@@ -54,7 +64,7 @@ var InputField = AbstractField.extend({
* @override
*/
activate: function () {
- this.$el.focus();
+ this.$input.focus();
setTimeout(this.$input.select.bind(this.$input), 0);
},
@@ -78,19 +88,6 @@ var InputField = AbstractField.extend({
//--------------------------------------------------------------------------
/**
- * 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.$input = this.$el;
- this._prepareInput(this.$input);
- },
-
- /**
* Formats an input element for edit mode. This is in a separate function so
* extending widgets can use it on their input without having input as tagName.
*
@@ -113,6 +110,19 @@ var InputField = AbstractField.extend({
},
/**
+ * 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.$input = this.$el;
+ this._prepareInput(this.$input);
+ },
+
+ /**
* Resets the content to the formated value in readonly mode.
*
* @override
@@ -127,6 +137,14 @@ var InputField = AbstractField.extend({
//--------------------------------------------------------------------------
/**
+ * We immediately notify the outside world when this input loses focus.
+ *
+ * @private
+ */
+ _onFocusout: function () {
+ this._setValue(this.$input.val());
+ },
+ /**
* Implement keyboard movements. Mostly useful for its environment, such
* as a list view.
*
@@ -211,22 +229,6 @@ var FieldDate = InputField.extend({
},
//--------------------------------------------------------------------------
- // Public
- //--------------------------------------------------------------------------
-
- /**
- * Automatically selects the input associated with the datepicker widget.
- * When entering this field via a tab mechanism in list view for example.
- *
- * @override
- */
- activate: function () {
- var $input = this.datewidget.$input;
- $input.focus();
- setTimeout($input.select.bind($input), 0);
- },
-
- //--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
@@ -247,6 +249,7 @@ var FieldDate = InputField.extend({
*/
_renderEdit: function () {
this.datewidget.set_value(this.value);
+ this.$input = this.datewidget.$input;
},
});