').done(function() {
self.progressbar.$el.addClass(self.$el.attr('class'));
self.replaceElement(self.progressbar.$el);
self.progressbar.on('update', self, function(update) {
self.set('value', update.changed_value);
});
});
},
render_value: function() {
this.progressbar.set_value(this.get('value'));
},
});
/**
The PercentPie field expect a float from 0 to 100.
*/
var FieldPercentPie = common.AbstractField.extend({
template: 'FieldPercentPie',
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;
});
}
});
/**
The FieldBarChart expectsa list of values (indeed)
*/
var FieldBarChart = common.AbstractField.extend({
template: 'FieldBarChart',
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 FieldSelection = common.AbstractField.extend(common.ReinitializeFieldMixin, {
template: 'FieldSelection',
events: {
'change select': 'store_dom_value',
},
init: function(field_manager, node) {
this._super(field_manager, node);
this.set("value", false);
this.set("values", []);
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"))) {
this.set("domain", domain);
}
});
},
initialize_field: function() {
common.ReinitializeFieldMixin.initialize_field.call(this);
this.on("change:domain", this, this.query_values);
this.set("domain", new data.CompoundDomain(this.build_domain()).eval());
this.on("change:values", this, this.render_value);
},
query_values: function() {
var self = this;
var def;
if (this.field.type === "many2one") {
var model = new Model(this.field.relation);
def = model.call("name_search", ['', this.get("domain")], {"context": this.build_context()});
} else {
var values = _.reject(this.field.selection, function (v) { return v[0] === false && v[1] === ''; });
def = $.when(values);
}
this.records_orderer.add(def).then(function(values) {
if (! _.isEqual(values, self.get("values"))) {
self.set("values", values);
}
});
},
initialize_content: function() {
// Flag indicating whether we're in an event chain containing a change
// event on the select, in order to know what to do on keyup[RETURN]:
// * If the user presses [RETURN] as part of changing the value of a
// selection, we should just let the value change and not let the
// event broadcast further (e.g. to validating the current state of
// the form in editable list view, which would lead to saving the
// 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);
},
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);
}
},
set_value: function(value_) {
value_ = value_ === null ? false : value_;
value_ = value_ instanceof Array ? value_[0] : value_;
this._super(value_);
},
render_value: function() {
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) {
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]));
} 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
});
}
});
/**
This widget is intended to display a warning near a label of a 'timezone' field
indicating if the browser timezone is identical (or not) to the selected timezone.
This widget depends on a field given with the param 'tz_offset_field', which contains
the time difference between UTC time and local time, in minutes.
*/
var TimezoneMismatch = FieldSelection.extend({
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(){
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(){
var user_offset = this.get('tz_offset');
if (user_offset) {
var offset = -(new Date().getTimezoneOffset());
var browser_offset = (offset < 0) ? "-" : "+";
browser_offset += _.str.sprintf("%02d", Math.abs(offset / 60));
browser_offset += _.str.sprintf("%02d", Math.abs(offset % 60));
return (browser_offset !== user_offset);
}
return false;
},
render_value: function(){
this._super.apply(this, arguments);
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);
}
}
});
var LabelSelection = FieldSelection.extend({
init: function(field_manager, node) {
this._super(field_manager, node);
this.classes = this.options && this.options.classes || {};
},
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($('
').addClass('label label-' + btn_class));
}
},
});
var FieldRadio = common.AbstractField.extend(common.ReinitializeFieldMixin, {
template: 'FieldRadio',
events: {
'click input': 'click_change_value'
},
init: function(field_manager, node) {
/* Radio button widget: Attributes options:
* - "horizontal" to display in column
* - "no_radiolabel" don't display text values
*/
this._super(field_manager, node);
this.selection = _.clone(this.field.selection) || [];
this.domain = false;
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();
},
click_change_value: function (event) {
var val = $(event.target).val();
val = this.field.type == "selection" ? val : +val;
if (val !== this.get_value()) {
this.set_value(val);
}
},
/** Get the selection and render it
* selection: [[identifier, value_to_display], ...]
* For selection fields: this is directly given by this.field.selection
* For many2one fields: perform a search on the relation of the many2one field
*/
get_selection: function() {
var self = this;
var selection = [];
var def = $.Deferred();
if (self.field.type == "many2one") {
var domain = pyeval.eval('domain', this.build_domain()) || [];
if (! _.isEqual(self.domain, domain)) {
self.domain = domain;
var ds = new data.DataSetStatic(self, self.field.relation, self.build_context());
ds.call('search', [self.domain])
.then(function (records) {
ds.name_get(records).then(function (records) {
selection = records;
def.resolve();
});
});
} else {
selection = self.selection;
def.resolve();
}
}
else if (self.field.type == "selection") {
selection = self.field.selection || [];
def.resolve();
}
return def.then(function () {
if (! _.isEqual(selection, self.selection)) {
self.selection = _.clone(selection);
self.renderElement();
self.render_value();
}
});
},
set_value: function (value_) {
if (this.field.type == "selection") {
value_ = _.find(this.field.selection, function (sel) { return sel[0] == value_;});
}
else if (!this.selection.length) {
this.selection = [value_];
}
this._super(value_);
},
get_value: function () {
var value = this.get('value');
return ((value instanceof Array)? value[0] : value) || false;
},
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] : "");
}
});
var FieldReference = common.AbstractField.extend(common.ReinitializeFieldMixin, {
template: 'FieldReference',
init: function(field_manager, node) {
this._super(field_manager, node);
this.reference_ready = true;
},
destroy_content: function() {
if (this.fm) {
this.fm.destroy();
this.fm = undefined;
}
},
initialize_content: function() {
var self = this;
var fm = new common.DefaultFieldManager(this);
this.fm = fm;
fm.extend_field_desc({
"selection": {
selection: this.field_manager.get_field_desc(this.name).selection,
type: "selection",
},
"m2o": {
relation: null,
type: "many2one",
},
});
this.selection = new FieldSelection(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
.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: {
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
.on('focused', null, function () {self.trigger('focused');})
.on('blurred', null, function () {self.trigger('blurred');});
},
on_selection_changed: function() {
if (this.reference_ready) {
this.internal_set_value([this.selection.get_value(), false]);
this.render_value();
}
},
data_changed: function() {
if (this.reference_ready) {
this.internal_set_value([this.selection.get_value(), this.m2o.get_value()]);
}
},
set_value: function(val) {
if (val) {
val = val.split(',');
val[0] = val[0] || false;
val[1] = val[0] ? (val[1] ? parseInt(val[1], 10) : val[1]) : false;
}
this._super(val || [false, false]);
},
get_value: function() {
return this.get('value')[0] && this.get('value')[1] ? (this.get('value')[0] + ',' + this.get('value')[1]) : false;
},
render_value: function() {
this.reference_ready = false;
if (!this.get("effective_readonly")) {
this.selection.set_value(this.get('value')[0]);
}
this.m2o.field.relation = this.get('value')[0];
this.m2o.set_value(this.get('value')[1]);
this.m2o.do_toggle(!!this.get('value')[0]);
this.reference_ready = true;
},
});
var FieldBinary = common.AbstractField.extend(common.ReinitializeFieldMixin, {
init: function(field_manager, node) {
var self = this;
this._super(field_manager, node);
this.binary_value = false;
this.useFileAPI = !!window.FileReader;
this.max_upload_size = 25 * 1024 * 1024; // 25Mo
if (!this.useFileAPI) {
this.fileupload_id = _.uniqueId('oe_fileupload');
$(window).on(this.fileupload_id, function() {
var args = [].slice.call(arguments).slice(1);
self.on_file_uploaded.apply(self, args);
});
}
},
stop: function() {
if (!this.useFileAPI) {
$(window).off(this.fileupload_id);
}
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();
});
},
on_file_change: function(e) {
var self = this;
var file_node = e.target;
if ((this.useFileAPI && file_node.files.length) || (!this.useFileAPI && $(file_node).val() !== '')) {
if (this.useFileAPI) {
var file = file_node.files[0];
if (file.size > this.max_upload_size) {
var msg = _t("The selected file exceed the maximum file size of %s.");
this.do_warn(_t("File upload"), _.str.sprintf(msg, utils.human_size(this.max_upload_size)));
return false;
}
var filereader = new FileReader();
filereader.readAsDataURL(file);
filereader.onloadend = function(upload) {
var data = upload.target.result;
data = data.split(',')[1];
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.$el.find('.oe_form_binary_progress').show();
this.$el.find('.oe_form_binary').hide();
}
},
on_file_uploaded: function(size, name, content_type, file_base64) {
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();
},
on_file_uploaded_and_valid: function(size, name, content_type, file_base64) {
},
on_save_as: function(ev) {
var value = this.get('value');
if (!value) {
this.do_warn(_t("Save As..."), _t("The field is empty, there's nothing to save !"));
ev.stopPropagation();
} else {
framework.blockUI();
var c = crash_manager;
var filename_fieldname = this.node.attrs.filename;
var filename_field = this.view.fields && this.view.fields[filename_fieldname];
this.session.get_file({
'url': '/web/content',
'data': {
'model': this.view.dataset.model,
'id': this.view.datarecord.id,
'field': this.name,
'filename_field': filename_fieldname,
'filename': filename_field ? filename_field.get('value') : null,
'download': true,
'data': utils.is_bin_size(value) ? null : value,
},
'complete': framework.unblockUI,
'error': c.rpc_error.bind(c)
});
ev.stopPropagation();
return false;
}
},
set_filename: function(value) {
var filename = this.node.attrs.filename;
if (filename) {
var field = this.field_manager.fields[filename];
if (field) {
field.set_value(value);
field._dirty_flag = true;
}
}
},
on_clear: function() {
if (this.get('value') !== false) {
this.binary_value = false;
this.internal_set_value(false);
}
return false;
}
});
var FieldBinaryFile = FieldBinary.extend({
template: 'FieldBinaryFile',
initialize_content: function() {
this._super();
if (this.get("effective_readonly")) {
var self = this;
this.$el.find('a').click(function(ev) {
if (self.get('value')) {
self.on_save_as(ev);
}
return false;
});
}
},
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') : '';
}
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);
}
}
},
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 $img = $(QWeb.render("FieldBinaryImage-img", { widget: this, url: url }));
$($img).click(function(e) {
if(self.view.get("actual_mode") == "view") {
var $button = $(".oe_form_button_edit");
$button.openerpBounce();
e.stopPropagation();
}
});
this.$el.find('> img').remove();
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_){
var changed = value_ !== this.get_value();
this._super.apply(this, arguments);
// By default, on binary images read, the server returns the binary size
// This is possible that two images have the exact same size
// Therefore we trigger the change in case the image value hasn't changed
// So the image is re-rendered correctly
if (!changed){
this.trigger("change:value", this, {
oldValue: value_,
newValue: value_
});
}
}
});
var FieldStatus = common.AbstractField.extend({
template: "FieldStatus",
init: function(field_manager, node) {
this._super(field_manager, node);
this.options.clickable = this.options.clickable || (this.node.attrs || {}).clickable || false;
this.options.visible = this.options.visible || (this.node.attrs || {}).statusbar_visible || false;
this.set({value: false});
this.selection = {'unfolded': [], 'folded': []};
this.set("selection", {'unfolded': [], 'folded': []});
this.selection_dm = new utils.DropMisordered();
this.dataset = new data.DataSetStatic(this, this.field.relation, this.build_context());
},
start: function() {
this.field_manager.on("view_content_has_changed", this, this.calc_domain);
this.calc_domain();
this.on("change:value", this, this.get_selection);
this.on("change:evaluated_selection_domain", this, this.get_selection);
this.on("change:selection", this, function() {
this.selection = this.get("selection");
this.render_value();
});
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('
');
}
this._super();
},
set_value: function(value_) {
if (value_ instanceof Array) {
value_ = value_[0];
}
this._super(value_);
},
render_value: function() {
var self = this;
var content = QWeb.render("FieldStatus.content", {
'widget': self,
'value_folded': _.find(self.selection.folded, function(i){return i[0] === self.get('value');})
});
self.$el.html(content);
},
calc_domain: function() {
var d = pyeval.eval('domain', this.build_domain());
var domain = []; //if there is no domain defined, fetch all the records
if (d.length) {
domain = ['|',['id', '=', this.get('value')]].concat(d);
}
if (! _.isEqual(domain, this.get("evaluated_selection_domain"))) {
this.set("evaluated_selection_domain", domain);
}
},
/** Get the selection and render it
* selection: [[identifier, value_to_display], ...]
* For selection fields: this is directly given by this.field.selection
* For many2one fields: perform a search on the relation of the many2one field
*/
get_selection: function() {
var self = this;
var selection_unfolded = [];
var selection_folded = [];
var fold_field = this.options.fold_field;
var calculation = _.bind(function() {
if (this.field.type == "many2one") {
return self.get_distant_fields().then(function (fields) {
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')) {
selection_folded.push([record.id, name]);
} else {
selection_unfolded.push([record.id, name]);
}
});
});
});
});
} else {
// For field type selection filter values according to
// statusbar_visible attribute of the field. For example:
// statusbar_visible="draft,open".
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) {
selection_unfolded.push(select[i]);
}
}
return $.when();
}
}, this);
this.selection_dm.add(calculation()).then(function () {
var selection = {'unfolded': selection_unfolded, 'folded': selection_folded};
if (! _.isEqual(selection, self.get("selection"))) {
self.set("selection", selection);
}
});
},
/*
* :deprecated: this feature will probably be removed with OpenERP v8
*/
get_distant_fields: function() {
var self = this;
if (! this.options.fold_field) {
this.distant_fields = {};
}
if (this.distant_fields) {
return $.when(this.distant_fields);
}
return new Model(self.field.relation).call("fields_get", [[this.options.fold_field]]).then(function(fields) {
self.distant_fields = fields;
return fields;
});
},
on_click_stage: function (ev) {
var self = this;
var $li = $(ev.currentTarget);
if (this.view.is_disabled) {
return;
}
var val;
if (this.field.type == "many2one") {
val = parseInt($li.data("id"), 10);
}
else {
val = $li.data("id");
}
if (val != self.get('value')) {
if (!this.view.datarecord.id ||
this.view.datarecord.id.toString().match(data.BufferedDataSet.virtual_id_regex)) {
// don't save, only set value for not-yet-saved many2ones
self.set_value(val);
}
else {
this.view.recursive_save().done(function() {
var change = {};
change[self.name] = val;
self.view.dataset.write(self.view.datarecord.id, change).done(function() {
self.view.reload();
});
});
}
}
},
});
var FieldMonetary = FieldFloat.extend({
template: "FieldMonetary",
widget_class: 'oe_form_field_float oe_form_field_monetary',
init: function() {
this._super.apply(this, arguments);
this.set({"currency": false});
var currency_field = (this.options && this.options.currency_field) || this.field.currency_field || 'currency_id';
if (currency_field) {
this.field_manager.on("field_changed:" + currency_field, this, function() {
this.set({"currency": this.field_manager.get_field_value(currency_field)});
});
}
this.on("change:currency", this, this.get_currency_info);
this.get_currency_info();
},
start: function() {
var tmp = this._super();
this.on("change:currency_info", this, this.update);
return tmp;
},
get_currency_info: function() {
var self = this;
if (this.get("currency") === false) {
this.set({"currency_info": null});
return;
}
return self.set({"currency_info": session.get_currency(self.get("currency"))});
},
update: function() {
if (this.view.options.is_list_editable){
return;
} else {
return this.reinitialize();
}
},
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);
},
format_value: function(val, def) {
return formats.format_value(val, {type: "float", digits: this.get_digits_precision()}, def);
},
});
/**
This widget is intended to be used on stat button numeric fields. It will display
the value many2many and one2many. It is a read-only field that will
display a simple string "