summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views/form_widgets.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js/views/form_widgets.js')
-rw-r--r--addons/web/static/src/js/views/form_widgets.js848
1 files changed, 333 insertions, 515 deletions
diff --git a/addons/web/static/src/js/views/form_widgets.js b/addons/web/static/src/js/views/form_widgets.js
index 2a2a36cdaba..2aeaaa17111 100644
--- a/addons/web/static/src/js/views/form_widgets.js
+++ b/addons/web/static/src/js/views/form_widgets.js
@@ -5,17 +5,17 @@ var core = require('web.core');
var crash_manager = require('web.crash_manager');
var data = require('web.data');
var datepicker = require('web.datepicker');
+var dom_utils = require('web.dom_utils');
+var Priority = require('web.Priority');
var ProgressBar = require('web.ProgressBar');
var Dialog = require('web.Dialog');
var common = require('web.form_common');
var formats = require('web.formats');
var framework = require('web.framework');
var Model = require('web.DataModel');
-var Priority = require('web.Priority');
var pyeval = require('web.pyeval');
var session = require('web.session');
var utils = require('web.utils');
-var dom_utils = require('web.dom_utils');
var _t = core._t;
var QWeb = core.qweb;
@@ -119,24 +119,25 @@ var WidgetButton = common.FormWidget.extend({
var FieldChar = common.AbstractField.extend(common.ReinitializeFieldMixin, {
template: 'FieldChar',
- widget_class: 'oe_form_field_char',
events: {
- 'change input': 'store_dom_value',
+ 'change': 'store_dom_value',
},
init: function (field_manager, node) {
this._super(field_manager, node);
this.password = this.node.attrs.password === 'True' || this.node.attrs.password === '1';
},
initialize_content: function() {
- this.setupFocus(this.$('input'));
+ if(!this.get('effective_readonly') && !this.$input) {
+ this.$input = this.$el;
+ }
+ this.setupFocus(this.$el);
+ },
+ destroy_content: function() {
+ this.$input = undefined;
},
store_dom_value: function () {
- if (!this.get('effective_readonly')
- && this.$('input').length
- && this.is_syntax_valid()) {
- this.internal_set_value(
- this.parse_value(
- this.$('input').val()));
+ if (this.$input && this.is_syntax_valid()) {
+ this.internal_set_value(this.parse_value(this.$input.val()));
}
},
commit_value: function () {
@@ -145,20 +146,19 @@ var FieldChar = common.AbstractField.extend(common.ReinitializeFieldMixin, {
},
render_value: function() {
var show_value = this.format_value(this.get('value'), '');
- if (!this.get("effective_readonly")) {
- this.$el.find('input').val(show_value);
+ if (this.$input) {
+ this.$input.val(show_value);
} else {
if (this.password) {
show_value = new Array(show_value.length + 1).join('*');
}
- this.$(".oe_form_char_content").text(show_value);
+ this.$el.text(show_value);
}
},
is_syntax_valid: function() {
- if (!this.get("effective_readonly") && this.$("input").size() > 0) {
+ if (this.$input) {
try {
- this.parse_value(this.$('input').val(), '');
- return true;
+ this.parse_value(this.$input.val(), '');
} catch(e) {
return false;
}
@@ -175,31 +175,30 @@ var FieldChar = common.AbstractField.extend(common.ReinitializeFieldMixin, {
return this.get('value') === '' || this._super();
},
focus: function() {
- var input = this.$('input:first')[0];
- return input ? input.focus() : false;
- },
- set_dimensions: function (height, width) {
- this._super(height, width);
- this.$('input').css({
- height: height,
- width: width
- });
- }
+ if (this.$input) {
+ return this.$input.focus();
+ }
+ return false;
+ },
});
-var KanbanSelection = FieldChar.extend({
+var KanbanSelection = common.AbstractField.extend({
template: "FormSelection",
- init: function (field_manager, node) {
- this._super(field_manager, node);
+ events: {
+ 'click a': function(e) {
+ e.preventDefault();
+ },
+ 'mouseup a': function(e) {
+ e.stopPropagation();
+ },
+ 'click li': 'set_kanban_selection'
},
start: function () {
- var self = this;
- this.states = [];
- this._super.apply(this, arguments);
// hook on form view content changed: recompute the states, because it may be related to the current stage
- this.getParent().on('view_content_has_changed', self, function () {
- self.render_value();
+ this.view.on('view_content_has_changed', this, function () {
+ this.render_value();
});
+ return this._super();
},
prepare_dropdown_selection: function() {
var self = this;
@@ -233,6 +232,7 @@ var KanbanSelection = FieldChar.extend({
this._super();
this.states = this.prepare_dropdown_selection();
var self = this;
+
// Adapt "FormSelection"
var current_state = _.find(this.states, function(state) {
return state.name === self.get('value');
@@ -248,7 +248,6 @@ var KanbanSelection = FieldChar.extend({
var $dropdown = this.$el.find('.dropdown-menu');
$dropdown.children().remove(); // remove old items
$items.appendTo($dropdown);
- this.$el.find('a').on('click', this.set_kanban_selection.bind(this));
},
/* setting the value: in view mode, perform an asynchronous call and reload
the form view; in edit mode, use set_value to save the new value that will
@@ -259,7 +258,7 @@ var KanbanSelection = FieldChar.extend({
var li = $(ev.target).closest('li');
if (li.length) {
var value = String(li.data('value'));
- if (this.view.get('actual_mode') == 'view') {
+ if (this.view.get('actual_mode') === 'view') {
var write_values = {};
write_values[self.name] = value;
return this.view.dataset._model.call(
@@ -339,66 +338,35 @@ var FieldID = FieldChar.extend({
var FieldEmail = FieldChar.extend({
template: 'FieldEmail',
- initialize_content: function() {
- this._super();
- var $button = this.$el.find('button');
- $button.click(this.on_button_clicked);
- this.setupFocus($button);
+ prefix: 'mailto',
+ init: function() {
+ this._super.apply(this, arguments);
+ this.clickable = true;
},
render_value: function() {
- if (!this.get("effective_readonly")) {
- this._super();
- } else {
- this.$el.find('a')
- .attr('href', 'mailto:' + this.get('value'))
- .text(this.get('value') || '');
- }
- },
- on_button_clicked: function() {
- if (!this.get('value') || !this.is_syntax_valid()) {
- this.do_warn(_t("E-mail Error"), _t("Can't send email to invalid e-mail address"));
- } else {
- location.href = 'mailto:' + this.get('value');
+ this._super();
+ if (this.get("effective_readonly") && this.clickable) {
+ this.$el.attr('href', this.prefix + ':' + this.get('value'));
}
}
});
-var FieldUrl = FieldChar.extend({
- template: 'FieldUrl',
- initialize_content: function() {
- this._super();
- var $button = this.$el.find('button');
- $button.click(this.on_button_clicked);
- this.setupFocus($button);
- },
+var FieldUrl = FieldEmail.extend({
render_value: function() {
- if (!this.get("effective_readonly")) {
- this._super();
- } else {
+ this._super();
+ if(this.get("effective_readonly")) {
var tmp = this.get('value');
var s = /(\w+):(.+)|^\.{0,2}\//.exec(tmp);
if (!s) {
tmp = "http://" + this.get('value');
}
var text = this.get('value') ? this.node.attrs.text || tmp : '';
- this.$el.find('a').attr('href', tmp).text(text);
- }
- },
- on_button_clicked: function() {
- if (!this.get('value')) {
- this.do_warn(_t("Resource Error"), _t("This resource is empty"));
- } else {
- var url = $.trim(this.get('value'));
- if(/^www\./i.test(url))
- url = 'http://'+url;
- window.open(url);
+ this.$el.attr('href', tmp).text(text);
}
}
});
var FieldFloat = FieldChar.extend({
- is_field_number: true,
- widget_class: 'oe_form_field_float',
init: function (field_manager, node) {
this._super(field_manager, node);
this.internal_set_value(0);
@@ -408,19 +376,18 @@ var FieldFloat = FieldChar.extend({
this.digits = this.field.digits;
}
},
+ initialize_content: function() {
+ this._super();
+ this.$el.addClass('o_form_field_number');
+ },
set_value: function(value_) {
if (value_ === false || value_ === undefined) {
- // As in GTK client, floats default to 0
- value_ = 0;
+ value_ = 0; // As in GTK client, floats default to 0
}
if (this.digits !== undefined && this.digits.length === 2) {
value_ = utils.round_decimals(value_, this.digits[1]);
}
- this._super.apply(this, [value_]);
- },
- focus: function () {
- var $input = this.$('input:first');
- return $input.length ? $input.select() : false;
+ this._super(value_);
}
});
@@ -474,7 +441,7 @@ var FieldCharDomain = common.AbstractField.extend(common.ReinitializeFieldMixin,
} else {
this.$('.o_count').text(_t('No selected record'));
var $arrow = this.$('button span').detach();
- this.$('button').text(_('Select records ')).append($("<span/>").addClass('fa fa-arrow-right'));
+ this.$('button').text(_t('Select records ')).append($("<span/>").addClass('fa fa-arrow-right'));
}
},
on_click: function(event) {
@@ -497,60 +464,58 @@ var FieldCharDomain = common.AbstractField.extend(common.ReinitializeFieldMixin,
},
});
-var FieldDatetime = common.AbstractField.extend(common.ReinitializeFieldMixin, {
- template: "FieldDatetime",
+var FieldDate = common.AbstractField.extend(common.ReinitializeFieldMixin, {
+ tagName: "span",
+ className: "o_form_field_date",
build_widget: function() {
- return new datepicker.DateTimeWidget(this);
+ return new datepicker.DateWidget(this);
},
- destroy_content: function() {
+ initialize_content: function() {
if (this.datewidget) {
this.datewidget.destroy();
this.datewidget = undefined;
}
- },
- initialize_content: function() {
+
if (!this.get("effective_readonly")) {
this.datewidget = this.build_widget();
- this.datewidget.on('datetime_changed', this, _.bind(function() {
+ this.datewidget.on('datetime_changed', this, function() {
this.internal_set_value(this.datewidget.get_value());
- }, this));
- this.datewidget.appendTo(this.$el);
- this.setupFocus(this.datewidget.$input);
+ });
+
+ var self = this;
+ this.datewidget.appendTo('<div>').done(function() {
+ self.datewidget.$el.addClass(self.$el.attr('class'));
+ self.replaceElement(self.datewidget.$el);
+ self.datewidget.$input.addClass('o_form_input');
+ self.setupFocus(self.datewidget.$input);
+ });
}
},
render_value: function() {
- if (!this.get("effective_readonly")) {
- this.datewidget.set_value(this.get('value'));
- } else {
+ if (this.get("effective_readonly")) {
this.$el.text(formats.format_value(this.get('value'), this, ''));
+ } else {
+ this.datewidget.set_value(this.get('value'));
}
},
is_syntax_valid: function() {
- if (!this.get("effective_readonly") && this.datewidget) {
- return this.datewidget.is_valid();
- }
- return true;
+ return this.get("effective_readonly") || !this.datewidget || this.datewidget.is_valid();
},
is_false: function() {
return this.get('value') === '' || this._super();
},
focus: function() {
- var input = this.datewidget && this.datewidget.$input[0];
- return input ? input.focus() : false;
- },
- set_dimensions: function (height, width) {
- this._super(height, width);
if (!this.get("effective_readonly")) {
- this.datewidget.$input.css('height', height);
+ return this.datewidget.$input.focus();
}
- }
+ return false;
+ },
});
-var FieldDate = FieldDatetime.extend({
- template: "FieldDate",
+var FieldDatetime = FieldDate.extend({
build_widget: function() {
- return new datepicker.DateWidget(this);
- }
+ return new datepicker.DateTimeWidget(this);
+ },
});
var FieldText = common.AbstractField.extend(common.ReinitializeFieldMixin, {
@@ -566,46 +531,37 @@ var FieldText = common.AbstractField.extend(common.ReinitializeFieldMixin, {
e.stopPropagation();
}
},
- 'change textarea': 'store_dom_value',
+ 'change': 'store_dom_value',
},
initialize_content: function() {
- if (! this.get("effective_readonly")) {
- this.$textarea = this.$el.find('textarea');
+ if (!this.get("effective_readonly")) {
this.auto_sized = false;
- this.default_height = this.$textarea.css('height');
- if (this.default_height === '0px') this.default_height = '90px';
- if (this.get("effective_readonly")) {
- this.$textarea.attr('disabled', 'disabled');
- }
- this.setupFocus(this.$textarea);
- } else {
- this.$textarea = undefined;
+ this.setupFocus(this.$el);
}
},
commit_value: function () {
- if (! this.get("effective_readonly") && this.$textarea) {
+ if (!this.get("effective_readonly")) {
this.store_dom_value();
}
return this._super();
},
store_dom_value: function () {
- this.internal_set_value(formats.parse_value(this.$textarea.val(), this));
+ this.internal_set_value(formats.parse_value(this.$el.val(), this));
},
render_value: function() {
- if (! this.get("effective_readonly")) {
- var show_value = formats.format_value(this.get('value'), this, '');
- this.$textarea.val(show_value);
- dom_utils.autoresize(this.$textarea, {parent: this, min_height: parseInt(this.default_height)});
- } else {
+ if (this.get("effective_readonly")) {
var txt = this.get("value") || '';
- this.$(".oe_form_text_content").text(txt);
+ this.$el.text(txt);
+ } else {
+ var show_value = formats.format_value(this.get('value'), this, '');
+ this.$el.val(show_value);
+ dom_utils.autoresize(this.$el, {parent: this});
}
},
is_syntax_valid: function() {
- if (!this.get("effective_readonly") && this.$textarea) {
+ if (!this.get("effective_readonly")) {
try {
- formats.parse_value(this.$textarea.val(), this, '');
- return true;
+ formats.parse_value(this.$el.val(), this, '');
} catch(e) {
return false;
}
@@ -616,51 +572,48 @@ var FieldText = common.AbstractField.extend(common.ReinitializeFieldMixin, {
return this.get('value') === '' || this._super();
},
focus: function($el) {
- var input = !this.get("effective_readonly") && this.$textarea && this.$textarea[0];
- return input ? input.focus() : false;
- },
- set_dimensions: function (height, width) {
- this._super(height, width);
- if (!this.get("effective_readonly") && this.$textarea) {
- this.$textarea.css({
- width: width,
- minHeight: height
- });
+ if(!this.get("effective_readonly")) {
+ return this.$el.focus();
}
+ return false;
+ },
+ set_dimensions: function(height, width) {
+ this.$el.css({
+ width: width,
+ minHeight: height,
+ });
},
});
var FieldBoolean = common.AbstractField.extend({
template: 'FieldBoolean',
+ events: {
+ 'click': function() {
+ this.internal_set_value(this.$checkbox.prop('checked'));
+ }
+ },
start: function() {
- var self = this;
- this.$checkbox = $("input", this.$el);
+ this.$checkbox = this.$('input');
+
+ this.$checkbox.prop('disabled', this.get("effective_readonly"));
+ this.on("change:effective_readonly", this, function() {
+ this.$checkbox.prop('disabled', this.get("effective_readonly"));
+ });
+
this.setupFocus(this.$checkbox);
- this.$el.click(_.bind(function() {
- this.internal_set_value(this.$checkbox.is(':checked'));
- }, this));
- var check_readonly = function() {
- self.$checkbox.prop('disabled', self.get("effective_readonly"));
- self.click_disabled_boolean();
- };
- this.on("change:effective_readonly", this, check_readonly);
- check_readonly.call(this);
- this._super.apply(this, arguments);
+
+ return this._super();
},
render_value: function() {
- this.$checkbox[0].checked = this.get('value');
+ this.$checkbox.prop('checked', this.get('value'));
},
focus: function() {
- var input = this.$checkbox && this.$checkbox[0];
- return input ? input.focus() : false;
- },
- click_disabled_boolean: function(){
- var $disabled = this.$el.find('input[type=checkbox]:disabled');
- $disabled.each(function (){
- $(this).next('div').remove();
- $(this).closest("span").append($('<div class="boolean"></div>'));
- });
- }
+ return this.$checkbox.focus();
+ },
+ set_dimensions: function(height, width) {}, // Checkboxes have a fixed height and width (even in list editable)
+ is_false: function() {
+ return false;
+ },
});
/**
@@ -706,9 +659,7 @@ var FieldBooleanButton = common.AbstractField.extend({
},
});
-/**
- The progressbar field expect a float from 0 to 100.
-*/
+// The progressbar field expects a float from 0 to 100.
var FieldProgressBar = common.AbstractField.extend(common.ReinitializeFieldMixin, {
initialize_content: function() {
if(this.progressbar) {
@@ -734,96 +685,41 @@ var FieldProgressBar = common.AbstractField.extend(common.ReinitializeFieldMixin
render_value: function() {
this.progressbar.set_value(this.get('value'));
},
+ is_false: function() {
+ return false;
+ },
});
-/**
- The PercentPie field expect a float from 0 to 100.
-*/
+// The PercentPie field expects a float from 0 to 100.
var FieldPercentPie = common.AbstractField.extend({
template: 'FieldPercentPie',
-
+ start: function() {
+ this.$left_mask = this.$('.o_mask').first();
+ this.$right_mask = this.$('.o_mask').last();
+ this.$pie_value = this.$('.o_pie_value');
+ return this._super();
+ },
render_value: function() {
- var value = this.get('value'),
- formatted_value = Math.round(value || 0) + '%',
- svg = this.$('svg')[0];
-
- svg.innerHTML = "";
- nv.addGraph(function() {
- var width = 42, height = 42;
- var chart = nv.models.pieChart()
- .width(width)
- .height(height)
- .margin({top: 0, right: 0, bottom: 0, left: 0})
- .donut(true)
- .showLegend(false)
- .showLabels(false)
- .color(['#7C7BAD','#DDD'])
- .donutRatio(0.62);
-
- chart.tooltip.enabled(false);
-
- d3.select(svg)
- .datum([{'x': 'value', 'y': value}, {'x': 'complement', 'y': 100 - value}])
- .transition()
- .call(chart)
- .attr('style', 'width: ' + width + 'px; height:' + height + 'px;');
-
- d3.select(svg)
- .append("text")
- .attr({x: width/2, y: height/2 + 3, 'text-anchor': 'middle'})
- .style({"font-size": "10px", "font-weight": "bold"})
- .text(formatted_value);
-
- return chart;
- });
-
- }
-});
+ var value = this.get('value') || 0, degValue = 360*value/100;
-/**
- The FieldBarChart expectsa list of values (indeed)
-*/
-var FieldBarChart = common.AbstractField.extend({
- template: 'FieldBarChart',
+ this.$right_mask.toggleClass('o_full', degValue >= 180);
- render_value: function() {
- var value = JSON.parse(this.get('value'));
- var svg = this.$('svg')[0];
- svg.innerHTML = "";
- nv.addGraph(function() {
- var width = 34, height = 34;
- var chart = nv.models.discreteBarChart()
- .x(function (d) { return d.tooltip; })
- .y(function (d) { return d.value; })
- .width(width)
- .height(height)
- .margin({top: 0, right: 0, bottom: 0, left: 0})
- .showValues(false)
- .transition(350)
- .showXAxis(false)
- .showYAxis(false);
-
- chart.tooltip.enabled(false);
-
- d3.select(svg)
- .datum([{key: 'values', values: value}])
- .transition()
- .call(chart)
- .attr('style', 'width: ' + (width + 4) + 'px; height: ' + (height + 8) + 'px;');
-
- nv.utils.windowResize(chart.update);
-
- return chart;
- });
-
+ var leftDeg = 'rotate(' + ((degValue < 180)? 180 : degValue) + 'deg)';
+ var rightDeg = 'rotate(' + ((degValue < 180)? degValue : 0) + 'deg)';
+ this.$left_mask.css({transform: leftDeg, msTransform: leftDeg, mozTransform: leftDeg, webkitTransform: leftDeg});
+ this.$right_mask.css({transform: rightDeg, msTransform: rightDeg, mozTransform: rightDeg, webkitTransform: rightDeg});
+
+ this.$pie_value.html(Math.round(value) + '%');
+ },
+ is_false: function() {
+ return false;
}
});
-
var FieldSelection = common.AbstractField.extend(common.ReinitializeFieldMixin, {
template: 'FieldSelection',
events: {
- 'change select': 'store_dom_value',
+ 'change': 'store_dom_value',
},
init: function(field_manager, node) {
this._super(field_manager, node);
@@ -832,7 +728,7 @@ var FieldSelection = common.AbstractField.extend(common.ReinitializeFieldMixin,
this.records_orderer = new utils.DropMisordered();
this.field_manager.on("view_content_has_changed", this, function() {
var domain = new data.CompoundDomain(this.build_domain()).eval();
- if (! _.isEqual(domain, this.get("domain"))) {
+ if (!_.isEqual(domain, this.get("domain"))) {
this.set("domain", domain);
}
});
@@ -869,27 +765,27 @@ var FieldSelection = common.AbstractField.extend(common.ReinitializeFieldMixin,
// current row or switching to the next one)
// * If the user presses [RETURN] with a select closed (side-effect:
// also if the user opened the select and pressed [RETURN] without
- // changing the selected value), takes the action as validating the
- // row
- var ischanging = false;
- var $select = this.$el.find('select')
- .change(function () { ischanging = true; })
- .click(function () { ischanging = false; })
- .keyup(function (e) {
- if (e.which !== 13 || !ischanging) { return; }
- e.stopPropagation();
- ischanging = false;
- });
- this.setupFocus($select);
+ // changing the selected value), takes the action as validating the row
+ if(!this.get('effective_readonly')) {
+ var ischanging = false;
+ this.$el
+ .change(function () { ischanging = true; })
+ .click(function () { ischanging = false; })
+ .keyup(function (e) {
+ if (e.which !== 13 || !ischanging) { return; }
+ e.stopPropagation();
+ ischanging = false;
+ });
+ this.setupFocus(this.$el);
+ }
},
commit_value: function () {
this.store_dom_value();
return this._super();
},
store_dom_value: function () {
- if (!this.get('effective_readonly') && this.$('select').length) {
- var val = JSON.parse(this.$('select').val());
- this.internal_set_value(val);
+ if (!this.get('effective_readonly')) {
+ this.internal_set_value(JSON.parse(this.$el.val()));
}
},
set_value: function(value_) {
@@ -901,28 +797,29 @@ var FieldSelection = common.AbstractField.extend(common.ReinitializeFieldMixin,
var values = this.get("values");
values = [[false, this.node.attrs.placeholder || '']].concat(values);
var found = _.find(values, function(el) { return el[0] === this.get("value"); }, this);
- if (! found) {
+ if (!found) {
found = [this.get("value"), _t('Unknown')];
values = [found].concat(values);
}
- if (! this.get("effective_readonly")) {
- this.$().html(QWeb.render("FieldSelectionSelect", {widget: this, values: values}));
- this.$("select").val(JSON.stringify(found[0]));
+ if (!this.get("effective_readonly")) {
+ this.$el.empty();
+ for(var i = 0 ; i < values.length ; i++) {
+ this.$el.append($('<option/>', {
+ value: JSON.stringify(values[i][0]),
+ html: values[i][1]
+ }))
+ }
+ this.$el.val(JSON.stringify(found[0]));
} else {
this.$el.text(found[1]);
}
},
focus: function() {
- var input = this.$('select:first')[0];
- return input ? input.focus() : false;
- },
- set_dimensions: function (height, width) {
- this._super(height, width);
- this.$('select').css({
- height: height,
- width: width
- });
- }
+ if (!this.get("effective_readonly")) {
+ return this.$el.focus();
+ }
+ return false;
+ },
});
/**
@@ -932,20 +829,20 @@ var FieldSelection = common.AbstractField.extend(common.ReinitializeFieldMixin,
the time difference between UTC time and local time, in minutes.
*/
var TimezoneMismatch = FieldSelection.extend({
- initialize_content: function(){
+ initialize_content: function() {
this._super.apply(this, arguments);
this.tz_offset_field = (this.options && this.options.tz_offset_field) || this.tz_offset_field || 'tz_offset';
this.set({"tz_offset": this.field_manager.get_field_value(this.tz_offset_field)});
this.on("change:tz_offset", this, this.render_value);
},
- start: function(){
+ start: function() {
this._super.apply(this, arguments);
// trigger a render_value when tz_offset field change
this.field_manager.on("field_changed:" + this.tz_offset_field, this, function() {
this.set({"tz_offset": this.field_manager.get_field_value(this.tz_offset_field)});
});
},
- check_timezone: function(){
+ check_timezone: function() {
var user_offset = this.get('tz_offset');
if (user_offset) {
var offset = -(new Date().getTimezoneOffset());
@@ -956,17 +853,15 @@ var TimezoneMismatch = FieldSelection.extend({
}
return false;
},
- render_value: function(){
+ render_value: function() {
this._super.apply(this, arguments);
+ this.$label.next('.o_tz_warning').remove();
if(this.check_timezone()){
- this.$label.find('.oe_tz_warning').remove();
var options = _.extend({
delay: { show: 501, hide: 0 },
title: _t("Timezone Mismatch : The timezone of your browser doesn't match the selected one. The time in Odoo is displayed according to your field timezone."),
});
- this.$label.css('white-space', 'normal');
- $(QWeb.render('WebClient.timezone_warning')).appendTo(this.$label);
- this.$label.find('.oe_tz_warning').tooltip(options);
+ $('<span/>').addClass('fa fa-exclamation-triangle o_tz_warning').insertAfter(this.$label).tooltip(options);
}
}
});
@@ -979,8 +874,8 @@ var LabelSelection = FieldSelection.extend({
render_value: function() {
this._super.apply(this, arguments);
if (this.get("effective_readonly")) {
- var btn_class = this.classes[this.get('value')] || 'default';
- this.$el.wrapInner($('<span/>').addClass('label label-' + btn_class));
+ var bt_class = this.classes[this.get('value')] || 'default';
+ this.$el.html($('<span/>', {html: this.$el.html()}).addClass('label label-' + bt_class));
}
},
});
@@ -1001,7 +896,6 @@ var FieldRadio = common.AbstractField.extend(common.ReinitializeFieldMixin, {
this.uniqueId = _.uniqueId("radio");
},
initialize_content: function () {
- this.on("change:effective_readonly", this, this.render_value);
this.field_manager.on("view_content_has_changed", this, this.get_selection);
this.get_selection();
},
@@ -1043,7 +937,7 @@ var FieldRadio = common.AbstractField.extend(common.ReinitializeFieldMixin, {
def.resolve();
}
return def.then(function () {
- if (! _.isEqual(selection, self.selection)) {
+ if (!_.isEqual(selection, self.selection)) {
self.selection = _.clone(selection);
self.renderElement();
self.render_value();
@@ -1066,14 +960,16 @@ var FieldRadio = common.AbstractField.extend(common.ReinitializeFieldMixin, {
},
render_value: function () {
var self = this;
- this.$el.toggleClass("oe_readonly", this.get('effective_readonly'));
- this.$("input").filter(function () {return this.value == self.get_value();}).prop("checked", true);
- this.$(".oe_radio_readonly").text(this.get('value') ? this.get('value')[1] : "");
+ if(this.get('effective_readonly')) {
+ this.$el.html(this.get('value')? this.get('value')[1] : "");
+ } else {
+ this.$("input").filter(function() {return this.value == self.get_value();}).prop("checked", true);
+ }
}
});
var FieldReference = common.AbstractField.extend(common.ReinitializeFieldMixin, {
- template: 'FieldReference',
+ className: 'o_row',
init: function(field_manager, node) {
this._super(field_manager, node);
this.reference_ready = true;
@@ -1086,9 +982,8 @@ var FieldReference = common.AbstractField.extend(common.ReinitializeFieldMixin,
},
initialize_content: function() {
var self = this;
- var fm = new common.DefaultFieldManager(this);
- this.fm = fm;
- fm.extend_field_desc({
+ this.fm = new common.DefaultFieldManager(this);
+ this.fm.extend_field_desc({
"selection": {
selection: this.field_manager.get_field_desc(this.name).selection,
type: "selection",
@@ -1098,23 +993,23 @@ var FieldReference = common.AbstractField.extend(common.ReinitializeFieldMixin,
type: "many2one",
},
});
- this.selection = new FieldSelection(fm, { attrs: {
+ this.selection = new FieldSelection(this.fm, { attrs: {
name: 'selection',
modifiers: JSON.stringify({readonly: this.get('effective_readonly')}),
}});
this.selection.on("change:value", this, this.on_selection_changed);
- this.selection.appendTo(this.$(".oe_form_view_reference_selection"));
+ this.selection.appendTo(this.$el);
this.selection
.on('focused', null, function () {self.trigger('focused');})
.on('blurred', null, function () {self.trigger('blurred');});
var FieldMany2One = core.form_widget_registry.get('many2one');
- this.m2o = new FieldMany2One(fm, { attrs: {
+ this.m2o = new FieldMany2One(this.fm, { attrs: {
name: 'Referenced Document',
modifiers: JSON.stringify({readonly: this.get('effective_readonly')}),
}});
this.m2o.on("change:value", this, this.data_changed);
- this.m2o.appendTo(this.$(".oe_form_view_reference_m2o"));
+ this.m2o.appendTo(this.$el);
this.m2o
.on('focused', null, function () {self.trigger('focused');})
.on('blurred', null, function () {self.trigger('blurred');});
@@ -1151,6 +1046,9 @@ var FieldReference = common.AbstractField.extend(common.ReinitializeFieldMixin,
this.m2o.do_toggle(!!this.get('value')[0]);
this.reference_ready = true;
},
+ is_false: function() {
+ return !this.get_value();
+ },
});
var FieldBinary = common.AbstractField.extend(common.ReinitializeFieldMixin, {
@@ -1161,7 +1059,7 @@ var FieldBinary = common.AbstractField.extend(common.ReinitializeFieldMixin, {
this.useFileAPI = !!window.FileReader;
this.max_upload_size = 25 * 1024 * 1024; // 25Mo
if (!this.useFileAPI) {
- this.fileupload_id = _.uniqueId('oe_fileupload');
+ this.fileupload_id = _.uniqueId('o_fileupload');
$(window).on(this.fileupload_id, function() {
var args = [].slice.call(arguments).slice(1);
self.on_file_uploaded.apply(self, args);
@@ -1175,13 +1073,14 @@ var FieldBinary = common.AbstractField.extend(common.ReinitializeFieldMixin, {
this._super.apply(this, arguments);
},
initialize_content: function() {
- var self= this;
- this.$('input.o_form_input_file').change(this.on_file_change);
- this.$('button.oe_form_binary_file_save').click(this.on_save_as);
- this.$('.oe_form_binary_file_clear').click(this.on_clear);
- this.$('.oe_form_binary_file_edit').click(function() {
- self.$('input.o_form_input_file').click();
+ this.$inputFile = this.$('.o_form_input_file');
+ this.$inputFile.change(this.on_file_change);
+ var self = this;
+ this.$('.o_select_file_button').click(function() {
+ self.$inputFile.click();
});
+ this.$('.o_save_file_button').click(this.on_save_as);
+ this.$('.o_clear_file_button').click(this.on_clear);
},
on_file_change: function(e) {
var self = this;
@@ -1202,26 +1101,28 @@ var FieldBinary = common.AbstractField.extend(common.ReinitializeFieldMixin, {
self.on_file_uploaded(file.size, file.name, file.type, data);
};
} else {
- this.$el.find('form.o_form_binary_form input[name=session_id]').val(this.session.session_id);
- this.$el.find('form.o_form_binary_form').submit();
+ this.$('form.o_form_binary_form input[name=session_id]').val(this.session.session_id);
+ this.$('form.o_form_binary_form').submit();
}
- this.$el.find('.oe_form_binary_progress').show();
- this.$el.find('.oe_form_binary').hide();
+ this.$('.o_form_binary_progress').show();
+ this.$('button').hide();
}
},
- on_file_uploaded: function(size, name, content_type, file_base64) {
+ on_file_uploaded: function(size, name) {
if (size === false) {
this.do_warn(_t("File Upload"), _t("There was a problem while uploading your file"));
// TODO: use openerp web crashmanager
console.warn("Error while uploading file : ", name);
} else {
- this.filename = name;
this.on_file_uploaded_and_valid.apply(this, arguments);
}
- this.$el.find('.oe_form_binary_progress').hide();
- this.$el.find('.oe_form_binary').show();
+ this.$('.o_form_binary_progress').hide();
+ this.$('button').show();
},
on_file_uploaded_and_valid: function(size, name, content_type, file_base64) {
+ this.binary_value = true;
+ this.set_filename(name);
+ this.set_value(file_base64);
},
on_save_as: function(ev) {
var value = this.get('value');
@@ -1248,7 +1149,6 @@ var FieldBinary = common.AbstractField.extend(common.ReinitializeFieldMixin, {
'error': c.rpc_error.bind(c)
});
ev.stopPropagation();
- return false;
}
},
set_filename: function(value) {
@@ -1262,129 +1162,95 @@ var FieldBinary = common.AbstractField.extend(common.ReinitializeFieldMixin, {
}
},
on_clear: function() {
- if (this.get('value') !== false) {
- this.binary_value = false;
- this.internal_set_value(false);
- }
- return false;
+ this.binary_value = false;
+ this.set_filename('');
+ this.set_value(false); // FIXME do not really remove the value
}
});
var FieldBinaryFile = FieldBinary.extend({
template: 'FieldBinaryFile',
initialize_content: function() {
+ var self = this;
this._super();
if (this.get("effective_readonly")) {
- var self = this;
- this.$el.find('a').click(function(ev) {
+ this.$el.click(function(ev) {
if (self.get('value')) {
self.on_save_as(ev);
}
return false;
});
+ } else {
+ this.$input = this.$('.o_form_input').eq(0);
+ this.$input.on('click', function() {
+ self.$inputFile.click();
+ });
}
},
render_value: function() {
- var show_value;
- if (!this.get("effective_readonly")) {
- if (this.node.attrs.filename) {
- show_value = this.view.datarecord[this.node.attrs.filename] || '';
- } else {
- show_value = (this.get('value') !== null && this.get('value') !== undefined && this.get('value') !== false) ? this.get('value') : '';
+ var filename = this.view.datarecord[this.node.attrs.filename];
+ if (this.get("effective_readonly")) {
+ this.do_toggle(!!this.get('value'));
+ if (this.get('value')) {
+ this.$el.empty().append($("<span/>").addClass('fa fa-download'));
+ if (filename) {
+ this.$el.append(" " + filename);
+ }
}
- this.$el.find('input').eq(0).val(show_value);
} else {
- this.$el.find('a').toggle(!!this.get('value'));
- if (this.get('value')) {
- show_value = _t("Download");
- if (this.view)
- show_value += " " + (this.view.datarecord[this.node.attrs.filename] || '');
- this.$el.find('a').text(show_value);
+ if(this.get('value')) {
+ this.$el.children().removeClass('o_hidden');
+ this.$('.o_select_file_button').first().addClass('o_hidden');
+ this.$input.val(filename || this.get('value'));
+ } else {
+ this.$el.children().addClass('o_hidden');
+ this.$('.o_select_file_button').first().removeClass('o_hidden');
}
}
- },
- on_file_uploaded_and_valid: function(size, name, content_type, file_base64) {
- this.binary_value = true;
- this.set_filename(name);
- this.internal_set_value(file_base64);
- var show_value = name + " (" + utils.human_size(size) + ")";
- this.$el.find('input').eq(0).val(show_value);
- },
- on_clear: function() {
- this._super.apply(this, arguments);
- this.$el.find('input').eq(0).val('');
- this.set_filename('');
- },
- set_value: function(value_){
- var changed = value_ !== this.get_value();
- this._super.apply(this, arguments);
- // Trigger value change if size is the same
- if (!changed){
- this.trigger("change:value", this, {
- oldValue: value_,
- newValue: value_
- });
- }
- }
+ }
});
var FieldBinaryImage = FieldBinary.extend({
template: 'FieldBinaryImage',
placeholder: "/web/static/src/img/placeholder.png",
render_value: function() {
- var self = this;
- var url;
- this.session = session;
- if (this.get('value') && !utils.is_bin_size(this.get('value'))) {
- url = 'data:image/png;base64,' + this.get('value');
- } else if (this.get('value')) {
- var id = JSON.stringify(this.view.datarecord.id || null);
- var field = this.name;
- if (this.options.preview_image)
- field = this.options.preview_image;
- url = session.url('/web/image', {
- model: this.view.dataset.model,
- id: id,
- field: field,
- unique: (this.view.datarecord.__last_update || '').replace(/[^0-9]/g, ''),
- });
- } else {
- url = this.placeholder;
+ var url = this.placeholder;
+ if(this.get('value')) {
+ if(!utils.is_bin_size(this.get('value'))) {
+ url = 'data:image/png;base64,' + this.get('value');
+ } else {
+ url = session.url('/web/image', {
+ model: this.view.dataset.model,
+ id: JSON.stringify(this.view.datarecord.id || null),
+ field: (this.options.preview_image)? this.options.preview_image : this.name,
+ unique: (this.view.datarecord.__last_update || '').replace(/[^0-9]/g, ''),
+ });
+ }
}
- var $img = $(QWeb.render("FieldBinaryImage-img", { widget: this, url: url }));
- $($img).click(function(e) {
+
+ var $img = $(QWeb.render("FieldBinaryImage-img", {widget: this, url: url}));
+
+ var self = this;
+ $img.click(function(e) {
if(self.view.get("actual_mode") == "view") {
- var $button = $(".oe_form_button_edit");
+ var $button = $(".o_form_button_edit");
$button.openerpBounce();
e.stopPropagation();
}
});
- this.$el.find('> img').remove();
+ this.$('> img').remove();
+ if (self.options.size) {
+ $img.css("width", "" + self.options.size[0] + "px");
+ $img.css("height", "" + self.options.size[1] + "px");
+ }
this.$el.prepend($img);
- $img.load(function() {
- if (! self.options.size)
- return;
- $img.css("max-width", "" + self.options.size[0] + "px");
- $img.css("max-height", "" + self.options.size[1] + "px");
- });
$img.on('error', function() {
self.on_clear();
$img.attr('src', self.placeholder);
self.do_warn(_t("Image"), _t("Could not display the selected image."));
});
},
- on_file_uploaded_and_valid: function(size, name, content_type, file_base64) {
- this.internal_set_value(file_base64);
- this.binary_value = true;
- this.render_value();
- this.set_filename(name);
- },
- on_clear: function() {
- this._super.apply(this, arguments);
- this.render_value();
- this.set_filename('');
- },
- set_value: function(value_){
+ set_value: function(value_) {
var changed = value_ !== this.get_value();
this._super.apply(this, arguments);
// By default, on binary images read, the server returns the binary size
@@ -1397,7 +1263,16 @@ var FieldBinaryImage = FieldBinary.extend({
newValue: value_
});
}
- }
+ },
+ is_false: function() {
+ return false;
+ },
+ set_dimensions: function(height, width) {
+ this.$el.css({
+ maxWidth: width,
+ minHeight: height,
+ });
+ },
});
var FieldStatus = common.AbstractField.extend({
@@ -1423,13 +1298,14 @@ var FieldStatus = common.AbstractField.extend({
});
this.get_selection();
if (this.options.clickable) {
- this.$el.on('click','li[data-id]',this.on_click_stage);
- }
- if (this.$el.parent().is('header')) {
- this.$el.after('<div class="oe_clear"/>');
+ this.bind_stage_click();
}
this._super();
},
+ bind_stage_click: function () {
+ // This function is overriden in the enterprise webclient
+ this.$el.on('click','li[data-id]',this.on_click_stage);
+ },
set_value: function(value_) {
if (value_ instanceof Array) {
value_ = value_[0];
@@ -1468,15 +1344,15 @@ var FieldStatus = common.AbstractField.extend({
var fold_field = this.options.fold_field;
var calculation = _.bind(function() {
- if (this.field.type == "many2one") {
- return self.get_distant_fields().then(function (fields) {
+ if (this.field.type === "many2one") {
+ return self.get_distant_fields().then(function () {
return new data.DataSetSearch(self, self.field.relation, self.build_context(), self.get("evaluated_selection_domain"))
.read_slice(_.union(_.keys(self.distant_fields), ['id']), {}).then(function (records) {
var ids = _.pluck(records, 'id');
return self.dataset.name_get(ids).then(function (records_name) {
_.each(records, function (record) {
- var name = _.find(records_name, function (val) {return val[0] == record.id;})[1];
- if (fold_field && record[fold_field] && record.id != self.get('value')) {
+ var name = _.find(records_name, function (val) {return val[0] === record.id;})[1];
+ if (fold_field && record[fold_field] && record.id !== self.get('value')) {
selection_folded.push([record.id, name]);
} else {
selection_unfolded.push([record.id, name]);
@@ -1492,7 +1368,7 @@ var FieldStatus = common.AbstractField.extend({
var select = this.field.selection;
for(var i=0; i < select.length; i++) {
var key = select[i][0];
- if(key == this.get('value') || !this.options.visible || this.options.visible.indexOf(key) != -1) {
+ if(key === this.get('value') || !this.options.visible || this.options.visible.indexOf(key) !== -1) {
selection_unfolded.push(select[i]);
}
}
@@ -1529,13 +1405,12 @@ var FieldStatus = common.AbstractField.extend({
return;
}
var val;
- if (this.field.type == "many2one") {
+ if (this.field.type === "many2one") {
val = parseInt($li.data("id"), 10);
- }
- else {
+ } else {
val = $li.data("id");
}
- if (val != self.get('value')) {
+ if (val !== self.get('value')) {
this.view.recursive_save().done(function() {
var change = {};
change[self.name] = val;
@@ -1548,8 +1423,7 @@ var FieldStatus = common.AbstractField.extend({
});
var FieldMonetary = FieldFloat.extend({
- template: "FieldMonetary",
- widget_class: 'oe_form_field_float oe_form_field_monetary',
+ template: 'FieldMonetary',
init: function() {
this._super.apply(this, arguments);
this.set({"currency": false});
@@ -1567,6 +1441,23 @@ var FieldMonetary = FieldFloat.extend({
this.on("change:currency_info", this, this.update);
return tmp;
},
+ initialize_content: function() {
+ if(!this.get('effective_readonly')) {
+ this.$input = this.$('input');
+ this.add_symbol();
+ } else {
+ this.$input = undefined;
+ }
+
+ this._super();
+ },
+ add_symbol: function() {
+ var currency = this.get('currency_info');
+ if(currency) {
+ var before = (currency.position === 'before');
+ this.$el[(before)? 'prepend' : 'append']($('<span/>', {html: currency.symbol}));
+ }
+ },
get_currency_info: function() {
var self = this;
if (this.get("currency") === false) {
@@ -1576,15 +1467,21 @@ var FieldMonetary = FieldFloat.extend({
return self.set({"currency_info": session.get_currency(self.get("currency"))});
},
update: function() {
- if (this.view.options.is_list_editable){
+ if (this.view.options.is_list_editable) {
return;
} else {
return this.reinitialize();
}
},
+ render_value: function() {
+ this._super();
+ if(this.get('effective_readonly')) {
+ this.add_symbol();
+ }
+ },
get_digits_precision: function() {
return this.node.attrs.digits || this.field.digits || (this.get('currency_info') && this.get('currency_info').digits);
- },
+ },
parse_value: function(val, def) {
return formats.parse_value(val, {type: "float", digits: this.get_digits_precision()}, def);
},
@@ -1625,7 +1522,6 @@ var StatInfo = common.AbstractField.extend({
this.$el.html(QWeb.render("StatInfo", options));
this.$el.addClass('o_stat_info');
},
-
});
/**
@@ -1633,14 +1529,18 @@ var StatInfo = common.AbstractField.extend({
switching between a green bullet / gray bullet.
*/
var FieldToggleBoolean = common.AbstractField.extend({
+ template: "toggle_button",
+ events: {
+ 'click': 'set_toggle_button'
+ },
render_value: function () {
- this.icon = this.get_value() ? 'gtk-yes.png' : 'gtk-normal.png';
- this.$el.html(QWeb.render("FieldToggleBoolean", {'widget': this}));
- this.$('.oe_toggle_button').on('click', this.set_toggle_button.bind(this));
+ var $img = this.$('img');
+ var src = $img.attr('src');
+ $img.attr('src', src.substr(0, src.lastIndexOf('/')+1) + (this.get_value() ? 'gtk-yes.png' : 'gtk-normal.png'));
},
set_toggle_button: function () {
var self = this;
- var toggle_value = this.get_value() === false ? true: false;
+ var toggle_value = !this.get_value();
if (this.view.get('actual_mode') == 'view') {
var rec_values = {};
rec_values[self.node.attrs.name] = toggle_value;
@@ -1658,91 +1558,8 @@ var FieldToggleBoolean = common.AbstractField.extend({
reload_record: function () {
this.view.reload();
},
-});
-
-/**
- This widget is intended to be used in config settings.
- When checked, an upgrade popup is showed to the user.
-*/
-
-var AbstractFieldUpgrade = {
- events: {
- 'click input': 'on_click_input',
- },
-
- start: function() {
- this._super.apply(this, arguments);
-
- this.get_enterprise_label().after($("<span>", {
- text: "Enterprise",
- 'class': "label label-primary oe_inline"
- }));
- },
-
- open_dialog: function() {
- var message = $(QWeb.render('EnterpriseUpgrade'));
-
- var buttons = [
- {
- text: _t("Upgrade now"),
- classes: 'btn-primary',
- close: true,
- click: this.confirm_upgrade,
- },
- {
- text: _t("Cancel"),
- close: true,
- },
- ];
-
- return new Dialog(this, {
- size: 'medium',
- buttons: buttons,
- $content: $('<div>', {
- html: message,
- }),
- title: _t("Odoo Enterprise"),
- }).open();
- },
-
- confirm_upgrade: function() {
- new Model("res.users").call("search_count", [[["share", "=", false]]]).then(function(data) {
- framework.redirect("https://www.odoo.com/odoo-enterprise/upgrade?num_users=" + data);
- });
- },
-
- get_enterprise_label: function() {},
- on_click_input: function() {},
-};
-
-var UpgradeBoolean = FieldBoolean.extend(AbstractFieldUpgrade, {
- template: "FieldUpgradeBoolean",
-
- get_enterprise_label: function() {
- return this.$label;
- },
-
- on_click_input: function(event) {
- if(this.$checkbox.prop("checked")) {
- this.open_dialog().on('closed', this, function() {
- this.$checkbox.prop("checked", false);
- });
- }
- },
-});
-
-var UpgradeRadio = FieldRadio.extend(AbstractFieldUpgrade, {
-
- get_enterprise_label: function() {
- return this.$('label').last();
- },
-
- on_click_input: function(event) {
- if($(event.target).val() == 1) {
- this.open_dialog().on('closed', this, function() {
- this.$('input').first().prop("checked", true);
- });
- }
+ is_false: function() {
+ return false;
},
});
@@ -1770,7 +1587,6 @@ core.form_widget_registry
.add('toggle_button', FieldToggleBoolean)
.add('float', FieldFloat)
.add('percentpie', FieldPercentPie)
- .add('barchart', FieldBarChart)
.add('integer', FieldFloat)
.add('float_time', FieldFloat)
.add('progressbar', FieldProgressBar)
@@ -1782,9 +1598,7 @@ core.form_widget_registry
.add('kanban_state_selection', KanbanSelection)
.add('statinfo', StatInfo)
.add('timezone_mismatch', TimezoneMismatch)
- .add('label_selection', LabelSelection)
- .add('upgrade_boolean', UpgradeBoolean)
- .add('upgrade_radio', UpgradeRadio);
+ .add('label_selection', LabelSelection);
/**
@@ -1796,8 +1610,12 @@ core.form_widget_registry
core.form_tag_registry.add('button', WidgetButton);
return {
+ FieldBoolean: FieldBoolean,
FieldChar: FieldChar,
+ FieldEmail: FieldEmail,
FieldFloat: FieldFloat,
+ FieldRadio: FieldRadio,
+ FieldStatus: FieldStatus,
FieldMonetary: FieldMonetary,
WidgetButton: WidgetButton
};