diff options
| author | Aaron Bohy <aab@odoo.com> | 2016-04-21 13:58:22 +0200 |
|---|---|---|
| committer | Géry Debongnie <ged@odoo.com> | 2016-04-21 15:21:42 +0200 |
| commit | 6768bbfcc02e0f498110cda2ba9adbc2fd23d24c (patch) | |
| tree | 7dccb1019434582874b285276189b1b3dcbb96a9 /addons/web/static/src/js/views/form_widgets.js | |
| parent | e1bfd3fbda97ac7a64a585b07be161d5be606cf9 (diff) | |
| parent | 8e440b173e3b273b3aac541f2ec12527f67dfa60 (diff) | |
[MERGE] *: stop duplicating web
Avoid duplicating web addon in enterprise by extracting a common basis.
Enterprise features stay in enterprise, but use that common basis.
In web, mainly:
- JS refactoring and linting
- Conversion of .sass into .less split into multiple files
- Templates cleaning and DOM simplification
- Re-generation of web.pot, and update of .po files
Minor tweaks in some other addons to make them work with this new structure.
Diffstat (limited to 'addons/web/static/src/js/views/form_widgets.js')
| -rw-r--r-- | addons/web/static/src/js/views/form_widgets.js | 848 |
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 }; |
