summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js101
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js3
-rw-r--r--addons/web/static/src/js/views/control_panel/search/search_bar.js20
-rw-r--r--addons/web/static/src/js/views/control_panel/search/search_facet.js20
-rw-r--r--addons/web/static/src/js/views/kanban/search_panel.js5
-rw-r--r--addons/web/static/src/js/widgets/auto_complete.js14
6 files changed, 124 insertions, 39 deletions
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 160f445f1c4..eeda3d220b6 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -2329,11 +2329,28 @@ var FieldProgressBar = AbstractField.extend({
if (this.recordData[this.nodeOptions.current_value]) {
this.value = this.recordData[this.nodeOptions.current_value];
}
- this.max_value = this.recordData[this.nodeOptions.max_value] || 100;
+
+ // The few next lines determine if the widget can write on the record or not
+ this.editable_readonly = !!this.nodeOptions.editable_readonly;
+ // "hard" readonly
this.readonly = this.nodeOptions.readonly || !this.nodeOptions.editable;
- this.edit_max_value = this.nodeOptions.edit_max_value || false;
+
+ this.canWrite = !this.readonly && (
+ this.mode === 'edit' ||
+ (this.editable_readonly && this.mode === 'readonly') ||
+ (this.viewType === 'kanban') // Keep behavior before commit
+ );
+
+ // Boolean to toggle if we edit the numerator (value) or the denominator (max_value)
+ this.edit_max_value = !!this.nodeOptions.edit_max_value;
+ this.max_value = this.recordData[this.nodeOptions.max_value] || 100;
+
this.title = _t(this.attrs.title || this.nodeOptions.title) || '';
- this.edit_on_click = !this.nodeOptions.edit_max_value || false;
+
+ // Ability to edit the field through the bar
+ // /!\ this feature is disabled
+ this.enableBarAsInput = false;
+ this.edit_on_click = this.enableBarAsInput && this.mode === 'readonly' && !this.edit_max_value;
this.write_mode = false;
},
@@ -2341,19 +2358,19 @@ var FieldProgressBar = AbstractField.extend({
var self = this;
this._render_value();
- if (!this.readonly) {
+ if (this.canWrite) {
if (this.edit_on_click) {
this.$el.on('click', '.o_progress', function (e) {
var $target = $(e.currentTarget);
- self.value = Math.floor((e.pageX - $target.offset().left) / $target.outerWidth() * self.max_value);
+ var numValue = Math.floor((e.pageX - $target.offset().left) / $target.outerWidth() * self.max_value);
+ self.on_update(numValue);
self._render_value();
- self.on_update(self.value);
});
} else {
this.$el.on('click', function () {
if (!self.write_mode) {
var $input = $('<input>', {type: 'text', class: 'o_progressbar_value o_input'});
- $input.on('blur', _.bind(self.on_change_input, self));
+ $input.on('blur', self.on_change_input.bind(self));
self.$('.o_progressbar_value').replaceWith($input);
self.write_mode = true;
self._render_value();
@@ -2363,24 +2380,25 @@ var FieldProgressBar = AbstractField.extend({
}
return this._super();
},
+ /**
+ * Updates the widget with value
+ *
+ * @param {Number} value
+ */
on_update: function (value) {
- if (!isNaN(value)) {
- if (this.edit_max_value) {
- try {
- this.max_value = this._parseValue(value);
- this._isValid = true;
- } catch (e) {
- this._isValid = false;
- }
- var changes = {};
- changes[this.nodeOptions.max_value] = this.max_value;
- this.trigger_up('field_changed', {
- dataPointID: this.dataPointID,
- changes: changes,
- });
- } else {
- this._setValue(value);
- }
+ if (this.edit_max_value) {
+ this.max_value = value;
+ this._isValid = true;
+ var changes = {};
+ changes[this.nodeOptions.max_value] = this.max_value;
+ this.trigger_up('field_changed', {
+ dataPointID: this.dataPointID,
+ changes: changes,
+ });
+ } else {
+ // _setValues accepts string and will parse it
+ var formattedValue = this._formatValue(value);
+ this._setValue(formattedValue);
}
},
on_change_input: function (e) {
@@ -2388,29 +2406,42 @@ var FieldProgressBar = AbstractField.extend({
if (e.type === 'change' && !$input.is(':focus')) {
return;
}
- if (isNaN($input.val())) {
- this.do_warn(_t("Wrong value entered!"), _t("Only Integer Value should be valid."));
- } else {
- if (e.type === 'input') {
- this._render_value($input.val());
- if (parseFloat($input.val()) === 0) {
+
+ var parsedValue;
+ try {
+ // Cover all numbers with parseFloat
+ parsedValue = field_utils.parse.float($input.val());
+ } catch (error) {
+ this.do_warn(_t("Wrong value entered!"), _t("Only Integer or Float Value should be valid."));
+ }
+
+ if (parsedValue !== undefined) {
+ if (e.type === 'input') { // ensure what has just been typed in the input is a number
+ // returns NaN if not a number
+ this._render_value(parsedValue);
+ if (parsedValue === 0) {
$input.select();
}
- } else {
+ } else { // Implicit type === 'blur': we commit the value
if (this.edit_max_value) {
- this.max_value = $(e.target).val();
- } else {
- this.value = $(e.target).val() || 0;
+ parsedValue = parsedValue || 100;
}
+
var $div = $('<div>', {class: 'o_progressbar_value'});
this.$('.o_progressbar_value').replaceWith($div);
this.write_mode = false;
+ this.on_update(parsedValue);
this._render_value();
- this.on_update(this.edit_max_value ? this.max_value : this.value);
}
}
},
+ /**
+ * Renders the value
+ *
+ * @private
+ * @param {Number} v
+ */
_render_value: function (v) {
var value = this.value;
var max_value = this.max_value;
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index 74e1a239790..68abdf9855a 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -19,6 +19,8 @@ var config = require('web.config');
var core = require('web.core');
var mvc = require('web.mvc');
+var session = require('web.session');
+
var QWeb = core.qweb;
var AbstractController = mvc.Controller.extend(ActionMixin, {
@@ -477,6 +479,7 @@ var AbstractController = mvc.Controller.extend(ActionMixin, {
this.dp.add(this._rpc({
model: data.model,
method: data.method,
+ context: session.user_context,
})).then(function (action) {
if (action !== undefined) {
self.do_action(action, options);
diff --git a/addons/web/static/src/js/views/control_panel/search/search_bar.js b/addons/web/static/src/js/views/control_panel/search/search_bar.js
index 6248489922c..9063b2aca50 100644
--- a/addons/web/static/src/js/views/control_panel/search/search_bar.js
+++ b/addons/web/static/src/js/views/control_panel/search/search_bar.js
@@ -9,6 +9,8 @@ var Widget = require('web.Widget');
var SearchBar = Widget.extend({
template: 'SearchView.SearchBar',
events: _.extend({}, Widget.prototype.events, {
+ 'compositionend .o_searchview_input': '_onCompositionendInput',
+ 'compositionstart .o_searchview_input': '_onCompositionstartInput',
'keydown': '_onKeydown',
}),
/**
@@ -34,6 +36,7 @@ var SearchBar = Widget.extend({
this.autoCompleteSources = [];
this.searchFacets = [];
+ this._isInputComposing = false;
},
/**
* @override
@@ -208,10 +211,27 @@ var SearchBar = Widget.extend({
}
},
/**
+ * @rivate
+ * @param {CompositionEvent} ev
+ */
+ _onCompositionendInput: function () {
+ this._isInputComposing = false;
+ },
+ /**
+ * @rivate
+ * @param {CompositionEvent} ev
+ */
+ _onCompositionstartInput: function () {
+ this._isInputComposing = true;
+ },
+ /**
* @private
* @param {KeyEvent} e
*/
_onKeydown: function (e) {
+ if (this._isInputComposing) {
+ return;
+ }
switch(e.which) {
case $.ui.keyCode.LEFT:
this._focusPreceding();
diff --git a/addons/web/static/src/js/views/control_panel/search/search_facet.js b/addons/web/static/src/js/views/control_panel/search/search_facet.js
index ca9a7ad6225..3f18597cccf 100644
--- a/addons/web/static/src/js/views/control_panel/search/search_facet.js
+++ b/addons/web/static/src/js/views/control_panel/search/search_facet.js
@@ -10,6 +10,8 @@ var SearchFacet = Widget.extend({
template: 'SearchView.SearchFacet',
events: _.extend({}, Widget.prototype.events, {
'click .o_facet_remove': '_onFacetRemove',
+ 'compositionend': '_onCompositionend',
+ 'compositionstart': '_onCompositionstart',
'keydown': '_onKeydown',
}),
/**
@@ -26,6 +28,7 @@ var SearchFacet = Widget.extend({
});
this.separator = this._getSeparator();
this.icon = this._getIcon();
+ this._isComposing = false;
},
//--------------------------------------------------------------------------
@@ -107,6 +110,20 @@ var SearchFacet = Widget.extend({
/**
* @private
+ * @param {CompositionEvent} ev
+ */
+ _onCompositionend: function (ev) {
+ this._isComposing = false;
+ },
+ /**
+ * @private
+ * @param {CompositionEvent} ev
+ */
+ _onCompositionstart: function (ev) {
+ this._isComposing = true;
+ },
+ /**
+ * @private
*/
_onFacetRemove: function () {
this.trigger_up('facet_removed', {group: this.facet});
@@ -116,6 +133,9 @@ var SearchFacet = Widget.extend({
* @param {KeyboardEvent} ev
*/
_onKeydown: function (ev) {
+ if (this._isComposing) {
+ return;
+ }
switch (ev.which) {
case $.ui.keyCode.BACKSPACE:
this.trigger_up('facet_removed', {group: this.facet});
diff --git a/addons/web/static/src/js/views/kanban/search_panel.js b/addons/web/static/src/js/views/kanban/search_panel.js
index 730c9b83ae2..788c8e5ed20 100644
--- a/addons/web/static/src/js/views/kanban/search_panel.js
+++ b/addons/web/static/src/js/views/kanban/search_panel.js
@@ -140,8 +140,9 @@ var SearchPanel = Widget.extend({
});
_.map(values, function (value) {
var value = category.values[value.id];
- if (value.parentId) {
- category.values[value.parentId].childrenIds.push(value.id);
+ var parentCategoryId = value.parentId;
+ if (parentCategoryId && parentCategoryId in category.values) {
+ category.values[parentCategoryId].childrenIds.push(value.id);
}
});
category.rootIds = _.filter(_.map(values, function (value) {
diff --git a/addons/web/static/src/js/widgets/auto_complete.js b/addons/web/static/src/js/widgets/auto_complete.js
index 1bb00be8d38..30c38690d17 100644
--- a/addons/web/static/src/js/widgets/auto_complete.js
+++ b/addons/web/static/src/js/widgets/auto_complete.js
@@ -29,16 +29,23 @@ return Widget.extend({
this.searching = true;
this.search_string = '';
this.current_search = null;
+ this._isInputComposing = false;
},
start: function () {
var self = this;
+ this.$input.on('compositionend', function (ev) {
+ self._isInputComposing = false;
+ });
+ this.$input.on('compositionstart', function (ev) {
+ self._isInputComposing = true;
+ });
this.$input.on('keyup', function (ev) {
- if (ev.which === $.ui.keyCode.RIGHT) {
+ if (ev.which === $.ui.keyCode.RIGHT && !self._isInputComposing) {
self.searching = true;
ev.preventDefault();
return;
}
- if (ev.which === $.ui.keyCode.ENTER) {
+ if (ev.which === $.ui.keyCode.ENTER && !self._isInputComposing) {
if (self.search_string.length) {
self.select_item(ev);
}
@@ -68,6 +75,9 @@ return Widget.extend({
}
});
this.$input.on('keydown', function (ev) {
+ if (self._isInputComposing) {
+ return;
+ }
switch (ev.which) {
case $.ui.keyCode.ENTER: