* view should be displayed (if there is one active).
*/
searchable: false,
- readonly : false,
template: "FormView",
display_name: _lt('Form'),
/**
this.model = dataset.model;
this.view_id = view_id || false;
this.fields_view = {};
- this.widgets = {};
- this.widgets_counter = 0;
this.fields = {};
this.fields_order = [];
this.datarecord = {};
this.on_change_mutex = new $.Mutex();
this.reload_mutex = new $.Mutex();
this.set({"force_readonly": false});
+ this.rendering_engine = new openerp.web.FormRenderingEngine(this);
},
start: function() {
this._super();
this.sidebar.attachments.destroy();
this.sidebar.destroy();
}
- _.each(this.widgets, function(w) {
+ _.each(this.get_widgets(), function(w) {
w.destroy();
});
this._super();
this.fields_order = [];
this.fields_view = data;
- var form = new openerp.web.FormRenderingEngine(this, data);
- form.appendTo(this.$element.find('.oe_form_content'));
+ this.rendering_engine.set_fields_view(data);
+ this.rendering_engine.render_to(this.$element.find('.oe_form_container'));
this.$form_header = this.$element.find('.oe_form_header:first');
this.$form_header.find('div.oe_form_pager button[data-pager-action]').click(function() {
});
},
on_form_changed: function() {
- for (var w in this.widgets) {
- w = this.widgets[w];
+ _.each(this.get_widgets(), function(w) {
w.process_modifiers();
if (w.field) {
w.validate();
}
w.update_dom();
- }
+ });
},
do_notify_change: function() {
this.$element.addClass('oe_form_dirty');
}
// form field
if (self.fields[field]) {
- var value = self.fields[field].get_on_change_value();
+ var value = self.fields[field].get_value();
return value == null ? false : value;
}
// parent field
value = response.value[fieldname];
} else {
// otherwise get form value for field
- value = self.fields[fieldname].get_on_change_value();
+ value = self.fields[fieldname].get_value();
}
var condition = fieldname + '=' + value;
if (!first_invalid_field) {
first_invalid_field = f;
}
- } else if (f.name !== 'id' && !f.readonly && (!self.datarecord.id || f.is_dirty())) {
+ } else if (f.name !== 'id' && !f.get("readonly") && (!self.datarecord.id || f.is_dirty())) {
// Special case 'id' field, do not save this field
// on 'create' : save all non readonly fields
// on 'edit' : save non readonly modified fields
}
});
},
+ get_widgets: function() {
+ return _.filter(this.getChildren(), function(obj) {
+ return obj instanceof openerp.web.form.Widget;
+ });
+ },
get_fields_values: function(blacklist) {
blacklist = blacklist || [];
var values = {};
// or m2m
if (!value
|| field.invisible
- || field.readonly
+ || field.get("readonly")
|| field.field.type === 'one2many'
|| field.field.type === 'many2many') {
return false;
}
});
-openerp.web.FormRenderingEngine = openerp.web.Widget.extend({
- init: function(parent, fvg, registry) {
- var self = this;
- this._super.apply(this, arguments);
+/**
+ * Interface to be implemented by rendering engines for the form view.
+ */
+openerp.web.FormRenderingEngineInterface = {
+ set_fields_view: function(fields_view) {},
+ render_to: function($element) {},
+};
+
+/**
+ * Default rendering engine for the form view.
+ *
+ * It is necessary to set the view using set_view() before usage.
+ */
+openerp.web.FormRenderingEngine = openerp.web.Class.extend({
+ init: function(view) {
+ this.view = view;
+ this.legacy_mode = false;
+ },
+ set_fields_view: function(fvg) {
this.fvg = fvg;
- this.view = parent;
- this.fields_prefix = this.view.dataset ? this.view.dataset.model : '';
+ this.legacy_mode = (this.fvg.arch.tag === 'form');
+ },
+ set_registry: function(registry) {
+ this.registry = registry;
+ },
+ render_to: function($element) {
+ var self = this;
+ this.$element = $element;
// TODO: I know this will save the world and all the kitten for a moment,
// but one day, we will have to get rid of xml2json
- var xml = openerp.web.json_node_to_xml(fvg.arch),
- $form = this.$form = $(xml);
+ var xml = openerp.web.json_node_to_xml(this.fvg.arch);
+ this.$form = $(xml);
- // TODO: extract embeded views before preprocessing
- _.each(['field', 'group', 'notebook', 'separator', 'label'], function(tag) {
- var fn = self['process_' + tag];
- if (registry && registry.contains(tag)) {
- fn = registry.get_object(tag);
- }
- $form.find(tag).each(function() {
- fn.call(self, $(this), $form);
- });
- });
- },
- start: function() {
- var self = this;
- this._super.apply(this, arguments);
- this.$form.children().appendTo(this.$element);
+ this.process(this.$form);
+
+ this.$form.appendTo(this.$element);
// OpenERP views spec :
// - @width is obsolete ?
- // TODO: modifiers invisible. Add a special attribute, eg: data-invisible that should be used in order to create openerp.form.InvisibleWidgetG
this.$element.find('field, button').each(function() {
var $elem = $(this),
if (self.view.registry.contains(key)) {
var obj = self.view.registry.get_object(key);
var w = new (obj)(self.view, openerp.web.xml_to_json($elem[0]));
+ self.alter_field(w);
w.replace($elem);
}
});
+ $('<button>Debug layout</button>').appendTo(this.$element).click($.proxy(this.toggle_layout_debugging, this));
+ },
+ render_element: function(template, dict) {
+ dict = dict || {};
+ dict.legacy_mode = this.legacy_mode;
+ return $(QWeb.render(template, dict));
},
- process_field: function($field, $form) {
+ alter_field: function(field) {},
+ toggle_layout_debugging: function() {
+ if (!this.$element.has('.oe_layout_debug_cell:first').length) {
+ this.$element.find('.oe_form_group_cell').each(function() {
+ var text = 'W:' + ($(this).attr('width') || '') + ' - C:' + $(this).attr('colspan'),
+ $span = $('<span class="oe_layout_debug_cell"/>').text(text);
+ $span.prependTo($(this));
+ });
+ }
+ this.$element.toggleClass('oe_layout_debugging');
+
+ },
+ process: function($tag) {
+ var self = this;
+ var tagname = $tag[0].nodeName.toLowerCase();
+ var fn = self['process_' + tagname];
+ if (this.registry && this.registry.contains(tagname)) {
+ fn = this.registry.get_object(tagname);
+ }
+ if (fn) {
+ var args = [].slice.call(arguments);
+ args[0] = $tag;
+ return fn.apply(self, args);
+ } else {
+ // generic tag handling, just process children
+ $tag.children().each(function() {
+ self.process($(this));
+ });
+ return $tag;
+ }
+ },
+ process_form: function($form) {
+ var $new_form = this.render_element('FormRenderingForm', $form.getAttributes());
+ $dst = this.legacy_mode ? $new_form.find('group:first') : $new_form;
+ $form.children().appendTo($dst);
+ if ($form[0] === this.$form[0]) {
+ // If root element, replace it
+ this.$form = $new_form;
+ } else {
+ $form.before($new_form).remove();
+ }
+ this.process($new_form);
+ },
+ preprocess_field: function($field) {
var name = $field.attr('name'),
field_orm = this.fvg.fields[name],
field_string = $field.attr('string') || field_orm.string || '',
field_help = $field.attr('help') || field_orm.help || '',
field_colspan = parseInt($field.attr('colspan'), 10);
-
- if (!field_orm) {
- throw new Error("Field '" + name + "' specified in view could not be found.");
- }
-
if ($field.attr('nolabel') !== '1') {
- var $label = $form.find('label[for="' + name + '"]');
+ $field.attr('nolabel', '1');
+ var $label = this.$form.find('label[for="' + name + '"]');
if (!$label.length) {
field_string = $label.attr('string') || $label.text() || field_string;
field_help = $label.attr('help') || field_help;
- $('<label/>').attr({
+ $label = $('<label/>').attr({
'for' : name,
'string' : field_string,
'help' : field_help
- }).insertBefore($field).text();
+ });
+ $label.insertBefore($field);
if (field_colspan > 1) {
$field.attr('colspan', field_colspan - 1);
}
}
+ return $label;
}
+ },
+ process_field: function($field) {
+ var $label = this.preprocess_field($field);
+ if ($label)
+ this.process($label);
+ var name = $field.attr('name'),
+ field_orm = this.fvg.fields[name],
+ field_string = $field.attr('string') || field_orm.string || '',
+ field_help = $field.attr('help') || field_orm.help || '',
+ field_colspan = parseInt($field.attr('colspan'), 10);
+
+ if (!field_orm) {
+ throw new Error("Field '" + name + "' specified in view could not be found.");
+ }
+
$field.attr({
'widget' : $field.attr('widget') || field_orm.type,
'string' : field_string,
'help' : field_help
});
+ return $field;
},
- process_group: function($group, $form) {
- var self = this,
- $new_group = $(QWeb.render('FormRenderingGroup', $group.getAttributes())),
+ process_group: function($group) {
+ var self = this;
+ $group.children('field').each(function() {
+ self.preprocess_field($(this));
+ });
+ var $new_group = $(QWeb.render('FormRenderingGroup', $group.getAttributes())),
$table;
if ($new_group.is('table')) {
$table = $new_group;
$table = $new_group.find('table:first');
}
$table.addClass('oe_form_group');
- var $tr,
+ var $tr, $td,
cols = parseInt($group.attr('col') || 4, 10),
row_cols = cols;
- $group.children().each(function() {
+ var children = [];
+ $group.children().each(function(a,b,c) {
var $child = $(this),
colspan = parseInt($child.attr('colspan') || 1, 10),
tagName = $child[0].tagName.toLowerCase();
row_cols = cols;
}
row_cols -= colspan;
- var $td = $('<td/>').addClass('oe_form_group_cell').attr('colspan', colspan);
+ $td = $('<td/>').addClass('oe_form_group_cell').attr('colspan', colspan);
$tr.append($td.append($child));
+ children.push($child[0]);
});
+ if (row_cols) {
+ $td.attr('colspan', parseInt($td.attr('colspan'), 10) + row_cols);
+ }
$group.before($new_group).remove();
// Now compute width of cells
$table.find('tbody > tr').each(function() {
var to_compute = [],
+ row_cols = cols,
total = 100;
$(this).children().each(function() {
var $td = $(this),
if ($child.attr('orientation') === 'vertical') {
$td.addClass('oe_vertical_separator').attr('width', '1');
$td.empty();
- cols--;
+ row_cols--;
}
break;
case 'label':
if ($child.attr('for')) {
$td.attr('width', '1%');
- cols--;
+ row_cols--;
total--;
}
break;
to_compute.push($td);
}
});
- var unit = Math.floor(total / cols);
+ var unit = Math.floor(total / row_cols);
_.each(to_compute, function($td, i) {
var width = parseInt($td.attr('colspan'), 10) * unit;
$td.attr('width', ((i == to_compute.length - 1) ? total : width) + '%');
total -= width;
});
});
+ _.each(children, function(el) {
+ self.process($(el));
+ });
+ return $new_group;
},
- process_notebook: function($notebook, $form) {
+ process_notebook: function($notebook) {
+ var self = this;
var pages = [];
$notebook.find('> page').each(function() {
var $page = $(this),
page_attrs = $page.getAttributes();
page_attrs.id = _.uniqueId('notebook_page_');
pages.push(page_attrs);
- var $new_page = $(QWeb.render('FormRenderingNotebookPage', page_attrs));
- $page.children().appendTo($new_page);
+ var $new_page = self.render_element('FormRenderingNotebookPage', page_attrs),
+ $dst = self.legacy_mode ? $new_page.find('group:first') : $new_page;
+ $page.children().appendTo($dst);
$page.before($new_page).remove();
});
var $new_notebook = $(QWeb.render('FormRenderingNotebook', { pages : pages }));
$notebook.children().appendTo($new_notebook);
$notebook.before($new_notebook).remove();
+ $new_notebook.children().each(function() {
+ self.process($(this));
+ });
$new_notebook.tabs();
+ return $new_notebook;
},
- process_separator: function($separator, $form) {
+ process_separator: function($separator) {
var $new_separator = $(QWeb.render('FormRenderingSeparator', $separator.getAttributes()));
$separator.before($new_separator).remove();
- },
- process_label: function($label, $form) {
- var $new_label = $(QWeb.render('FormRenderingLabel', $label.getAttributes()));
+ return $new_separator;
+ },
+ process_label: function($label) {
+ var dict = $label.getAttributes();
+ var align = parseFloat(dict.align);
+ if (isNaN(align) || align === 1) {
+ align = 'right';
+ } else if (align === 0) {
+ align = 'left';
+ } else {
+ align = 'center';
+ }
+ dict.align = align;
+ var $new_label = $(QWeb.render('FormRenderingLabel', dict));
$label.before($new_label).remove();
+ return $new_label;
}
});
},
process_modifiers: function() {
var compute_domain = openerp.web.form.compute_domain;
+ var to_set = {};
for (var a in this.modifiers) {
- this[a] = compute_domain(this.modifiers[a], this.view.fields);
+ var val = compute_domain(this.modifiers[a], this.view.fields);
+ this[a] = val;
+ to_set[a] = val;
}
+ this.set(to_set);
},
update_dom: function() {
this.$element.toggle(!this.invisible);
this.check_disable();
},
check_disable: function() {
- var disabled = (this.readonly || this.force_disabled || !this.view.is_interactible_record());
+ var disabled = (this.force_disabled || !this.view.is_interactible_record());
this.$element.prop('disabled', disabled);
this.$element.css('color', disabled ? 'grey' : '');
}
* able to provide the features necessary for the fields to work.
*
* Properties:
- * - force_readonly: boolean, When it is true, all the fields should always appear
- * in read only mode, no matter what the value of their "readonly" property can be.
+ * - ...
*/
openerp.web.form.FieldManagerInterface = {
*
* Properties:
* - readonly: boolean. If set to true the field should appear in readonly mode.
- *
+ * - force_readonly: boolean, When it is true, the field should always appear
+ * in read only mode, no matter what the value of the "readonly" property can be.
* Events:
* - ...
*
init: function(field_manager, node) {
this._super(field_manager, node);
this.name = this.node.attrs.name;
- this.value = undefined;
+ this.value = false;
this.view.fields[this.name] = this;
this.view.fields_order.push(this.name);
this.type = this.node.attrs.widget;
this.required = this.modifiers['required'] === true;
this.invalid = this.dirty = false;
- // because I'm lazy to refactor right now
- this.on("change:readonly", this, function() {this.readonly = this.get("readonly");});
-
// some events to make the property "effective_readonly" sync automatically with "readonly" and
// "force_readonly"
this.set({"readonly": this.modifiers['readonly'] === true});
var test_effective_readonly = function() {
- this.set({"effective_readonly": this.get("readonly") || this.view.get("force_readonly")});
+ this.set({"effective_readonly": this.get("readonly") || this.get("force_readonly")});
};
- this.view.on("change:readonly", this, test_effective_readonly);
- this.view.on("change:force_readonly", this, test_effective_readonly);
+ this.on("change:readonly", this, test_effective_readonly);
+ this.on("change:force_readonly", this, test_effective_readonly);
_.bind(test_effective_readonly, this)();
+
+ // TODO: do something good about this
+ if (this.view) {
+ this.$label = this.view.$element.find('label[for="' + this.name + '"]');
+ if (this.$label.length) {
+ this.id_for_label = _.uniqueId(['field', this.type, this.name, ''].join('_'));
+ this.$label.attr('for', this.id_for_label);
+ } else {
+ this.$label;
+ }
+ }
},
start: function() {
this._super.apply(this, arguments);
return !this.invalid;
},
is_dirty: function() {
- return this.dirty && !this.readonly;
- },
- get_on_change_value: function() {
- return this.get_value();
+ return this.dirty && !this.get("effective_readonly");
},
update_dom: function(show_invalid) {
this._super.apply(this, arguments);
this.$element.find('.oe_field_translate').toggle(!!this.view.datarecord.id);
}
if (!this.disable_utility_classes) {
- this.$element.toggleClass('disabled', this.readonly);
+ this.$element.toggleClass('disabled', this.get("effective_readonly"));
this.$element.toggleClass('required', this.required);
if (show_invalid) {
this.$element.toggleClass('invalid', !this.is_valid());
}
}
- // one more shit code to avoid refactoring this.readonly right now
- this.set({"readonly": this.readonly});
},
on_ui_change: function() {
this.dirty = true;
}
});
-openerp.web.form.FieldChar = openerp.web.form.AbstractField.extend({
- template: 'FieldChar',
- init: function (view, node) {
- this._super(view, node);
- this.password = this.node.attrs.password === 'True' || this.node.attrs.password === '1';
- },
+/**
+ * A mixin to apply on any field that has to completely re-render when its readonly state
+ * switch.
+ */
+openerp.web.form.ReinitializeFieldMixin = {
+ /**
+ * Default implementation of start(), use it or call explicitly initialize_field().
+ */
start: function() {
- this._super.apply(this, arguments);
- this.bind_events();
+ this._super();
+ this.initialize_field();
+ },
+ initialize_field: function() {
this.on("change:effective_readonly", this, function() {
- this.render_element();
- this.bind_events();
+ this.destroy_content();
+ this.renderElement();
+ this.initialize_content();
this.render_value();
});
+ this.initialize_content();
+ this.render_value();
},
- bind_events: function() {
+ /**
+ * Called to destroy anything that could have been created previously, called before a
+ * re-initialization.
+ */
+ destroy_content: function() {},
+ /**
+ * Called to initialize the content.
+ */
+ initialize_content: function() {},
+ /**
+ * Called to render the value. Should also be explicitly called at the end of a set_value().
+ */
+ render_value: function() {},
+};
+
+openerp.web.form.FieldChar = openerp.web.form.AbstractField.extend(_.extend({}, openerp.web.form.ReinitializeFieldMixin, {
+ template: 'FieldChar',
+ init: function (view, node) {
+ this._super(view, node);
+ this.password = this.node.attrs.password === 'True' || this.node.attrs.password === '1';
+ },
+ initialize_content: function() {
this.$element.find('input').change(this.on_ui_change);
},
set_value: function(value) {
},
validate: function() {
this.invalid = false;
- try {
- var value = openerp.web.parse_value(this.$element.find('input').val(), this, '');
- this.invalid = this.required && value === '';
- } catch(e) {
- this.invalid = true;
+ if (!this.get("effective_readonly")) {
+ try {
+ var value = openerp.web.parse_value(this.$element.find('input').val(), this, '');
+ this.invalid = this.required && value === '';
+ } catch(e) {
+ this.invalid = true;
+ }
}
},
focus: function($element) {
this._super($element || this.$element.find('input:first'));
}
-});
+}));
openerp.web.form.FieldID = openerp.web.form.FieldChar.extend({
- update_dom: function() {
- this._super.apply(this, arguments);
- this.$element.find('input').prop('readonly', true);
- }
+
});
openerp.web.form.FieldEmail = openerp.web.form.FieldChar.extend({
template: 'FieldEmail',
- bind_events: function() {
+ initialize_content: function() {
this._super();
this.$element.find('button').click(this.on_button_clicked);
},
openerp.web.form.FieldUrl = openerp.web.form.FieldChar.extend({
template: 'FieldUrl',
- bind_events: function() {
+ initialize_content: function() {
this._super();
this.$element.find('button').click(this.on_button_clicked);
},
openerp.web.form.FieldFloat = openerp.web.form.FieldChar.extend({
init: function (view, node) {
this._super(view, node);
+ this.value = 0;
if (this.node.attrs.digits) {
- this.parse_digits(this.node.attrs.digits);
+ this.digits = py.eval(this.node.attrs.digits).toJSON();
} else {
this.digits = this.field.digits;
}
},
- parse_digits: function (digits_attr) {
- // could use a Python parser instead.
- var match = /^\s*[\(\[](\d+),\s*(\d+)/.exec(digits_attr);
- return [parseInt(match[1], 10), parseInt(match[2], 10)];
- },
set_value: function(value) {
if (value === false || value === undefined) {
// As in GTK client, floats default to 0
showButtonPanel: true
});
this.$element.find('img.oe_datepicker_trigger').click(function() {
- if (!self.readonly && !self.picker('widget').is(':visible')) {
+ if (!self.get("effective_readonly") && !self.picker('widget').is(':visible')) {
self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date());
self.$input_picker.show();
self.picker('show');
type_of_date: "date"
});
-openerp.web.form.FieldDatetime = openerp.web.form.AbstractField.extend({
+openerp.web.form.FieldDatetime = openerp.web.form.AbstractField.extend(_.extend({}, openerp.web.form.ReinitializeFieldMixin, {
template: "EmptyComponent",
build_widget: function() {
return new openerp.web.DateTimeWidget(this);
},
- start: function() {
- var self = this;
- this._super.apply(this, arguments);
- this.datewidget = this.build_widget();
- this.datewidget.on_change.add_last(this.on_ui_change);
- this.datewidget.appendTo(this.$element);
+ destroy_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_change.add_last(this.on_ui_change);
+ this.datewidget.appendTo(this.$element);
+ }
},
set_value: function(value) {
this._super(value);
- this.datewidget.set_value(value);
+ this.render_value();
},
- get_value: function() {
- return this.datewidget.get_value();
+ render_value: function() {
+ if (!this.get("effective_readonly")) {
+ this.datewidget.set_value(this.value);
+ } else {
+ this.$element.text(openerp.web.format_value(this.value, this, ''));
+ }
},
- update_dom: function() {
- this._super.apply(this, arguments);
- this.datewidget.set_readonly(this.readonly);
+ get_value: function() {
+ if (!this.get("effective_readonly")) {
+ return this.datewidget.get_value();
+ } else {
+ return this.value;
+ }
},
validate: function() {
- this.invalid = !this.datewidget.is_valid(this.required);
+ this.invalid = this.get("effective_readonly") || !this.datewidget.is_valid(this.required);
},
focus: function($element) {
- this._super($element || this.datewidget.$input);
+ this._super($element || (this.datewidget && this.datewidget.$input));
}
-});
+}));
openerp.web.form.FieldDate = openerp.web.form.FieldDatetime.extend({
build_widget: function() {
}
});
-openerp.web.form.FieldText = openerp.web.form.AbstractField.extend({
+openerp.web.form.FieldText = openerp.web.form.AbstractField.extend(_.extend({}, openerp.web.form.ReinitializeFieldMixin, {
template: 'FieldText',
- start: function() {
- this._super.apply(this, arguments);
- this.$textarea = this.$element.find('textarea').change(this.on_ui_change);
- this.resized = false;
+ initialize_content: function() {
+ this.$textarea = undefined;
+ if (!this.get("effective_readonly")) {
+ this.$textarea = this.$element.find('textarea').change(this.on_ui_change);
+ this.resized = false;
+ }
},
set_value: function(value) {
this._super.apply(this, arguments);
- var show_value = openerp.web.format_value(value, this, '');
- this.$textarea.val(show_value);
- if (!this.resized && this.view.options.resize_textareas) {
- this.do_resize(this.view.options.resize_textareas);
- this.resized = true;
- }
+ this.render_value();
},
- update_dom: function() {
- this._super.apply(this, arguments);
- this.$textarea.prop('readonly', this.readonly);
+ render_value: function() {
+ var show_value = openerp.web.format_value(this.value, this, '');
+ if (!this.get("effective_readonly")) {
+ this.$textarea.val(show_value);
+ if (!this.resized && this.view.options.resize_textareas) {
+ this.do_resize(this.view.options.resize_textareas);
+ this.resized = true;
+ }
+ } else {
+ this.$element.text(show_value);
+ }
},
set_value_from_ui: function() {
this.value = openerp.web.parse_value(this.$textarea.val(), this);
},
validate: function() {
this.invalid = false;
- try {
- var value = openerp.web.parse_value(this.$textarea.val(), this, '');
- this.invalid = this.required && value === '';
- } catch(e) {
- this.invalid = true;
+ if (!this.get("effective_readonly")) {
+ try {
+ var value = openerp.web.parse_value(this.$textarea.val(), this, '');
+ this.invalid = this.required && value === '';
+ } catch(e) {
+ this.invalid = true;
+ }
}
},
focus: function($element) {
reset: function() {
this.resized = false;
}
-});
+}));
openerp.web.form.FieldBoolean = openerp.web.form.AbstractField.extend({
template: 'FieldBoolean',
this._super.apply(this, arguments);
this.$element.progressbar({
value: this.value,
- disabled: this.readonly
+ disabled: this.get("effective_readonly")
});
},
set_value: function(value) {
// to replace view editor
});
-openerp.web.form.FieldSelection = openerp.web.form.AbstractField.extend({
+openerp.web.form.FieldSelection = openerp.web.form.AbstractField.extend(_.extend({}, openerp.web.form.ReinitializeFieldMixin, {
template: 'FieldSelection',
init: function(view, node) {
var self = this;
});
this.values.unshift([false, '']);
},
- start: function() {
- this._super.apply(this, arguments);
- this.bind_events();
- this.on("change:effective_readonly", this, function() {
- this.render_element();
- this.bind_events();
- this.render_value();
- });
- },
- bind_events: function() {
+ 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
focus: function($element) {
this._super($element || this.$element.find('select:first'));
}
-});
+}));
// jquery autocomplete tweak to allow html
(function() {
return dialog.$element;
};
-openerp.web.form.FieldMany2One = openerp.web.form.AbstractField.extend({
- template: 'EmptyComponent',
+openerp.web.form.FieldMany2One = openerp.web.form.AbstractField.extend(_.extend({}, openerp.web.form.ReinitializeFieldMixin, {
+ template: "FieldMany2One",
init: function(view, node) {
this._super(view, node);
this.limit = 7;
this.last_search = [];
this.tmp_value = undefined;
},
- start: function() {
- this._super();
- this.render_content();
- this.on("change:effective_readonly", this, function() {
- this.render_content();
- });
- },
- render_content: function() {
- this.$element.html("");
+ initialize_content: function() {
if (!this.get("effective_readonly"))
this.render_editable();
- else
- this.render_readonly();
this.render_value();
},
render_editable: function() {
- this.$element.html(QWeb.render("FieldMany2One", {widget: this}));
var self = this;
this.$input = this.$element.find("input");
this.$drop_down = this.$element.find(".oe-m2o-drop-down-button");
isSelecting = false;
});
},
- render_readonly: function() {
- this.$element.html(QWeb.render("FieldMany2One_readonly"));
- },
// autocomplete component content handling
get_search_result: function(request, response) {
var search_val = request.term;
focus: function ($element) {
this._super($element || this.$input);
}
-});
-openerp.web.check_interface(openerp.web.form.FieldMany2One, openerp.web.form.FieldInterface);
+}));
/*
# Values: (0, 0, { fields }) create
}
};
openerp.web.form.FieldOne2Many = openerp.web.form.AbstractField.extend({
- template: 'FieldOne2Many',
multi_selection: false,
init: function(view, node) {
this._super(view, node);
* TODO niv: clean those deferred stuff, it could be better
*/
openerp.web.form.FieldMany2Many = openerp.web.form.AbstractField.extend({
- template: 'FieldMany2Many',
multi_selection: false,
init: function(view, node) {
this._super(view, node);
- this.list_id = _.uniqueId("many2many");
this.is_loaded = $.Deferred();
this.initial_is_loaded = this.is_loaded;
this.is_setted = $.Deferred();
loaded.resolve();
});
$.async_when().then(function () {
- self.list_view.appendTo($("#" + self.list_id));
+ self.list_view.appendTo(self.$element);
});
return loaded;
},
);
var self = this;
pop.on_select_elements.add(function(element_ids) {
- _.each(element_ids, function(element_id) {
- if(! _.detect(self.dataset.ids, function(x) {return x == element_id;})) {
- self.dataset.set_ids([].concat(self.dataset.ids, [element_id]));
+ _.each(element_ids, function(one_id) {
+ if(! _.detect(self.dataset.ids, function(x) {return x == one_id;})) {
+ self.dataset.set_ids([].concat(self.dataset.ids, [one_id]));
self.m2m_field.on_ui_change();
self.reload_content();
}
this.new_object();
}
},
+ stop: function () {
+ this.$element.dialog('close');
+ this._super();
+ },
setup_search_view: function(search_defaults) {
var self = this;
if (this.searchview) {
'selectable': !self.options.disable_multiple_selection
}, self.options.list_view_options || {}));
self.view_list.popup = self;
- self.view_list.appendTo($("#" + self.element_id + "_view_list")).pipe(function() {
+ self.view_list.appendTo($(".oe-select-create-popup-view-list", self.$element)).pipe(function() {
self.view_list.do_show();
}).pipe(function() {
self.searchview.do_search();
});
});
});
- this.searchview.appendTo($("#" + this.element_id + "_search"));
+ this.searchview.appendTo($(".oe-select-create-popup-view-list", self.$element));
},
do_search: function(domains, contexts, groupbys) {
var self = this;
if (this.options.alternative_form_view) {
this.view_form.set_embedded_view(this.options.alternative_form_view);
}
- this.view_form.appendTo(this.$element.find("#" + this.element_id + "_view_form"));
+ this.view_form.appendTo(this.$element.find(".oe-select-create-popup-view-form"));
this.view_form.on_loaded.add_last(function() {
var $buttons = self.view_form.$element.find(".oe_form_buttons");
$buttons.html(QWeb.render("SelectCreatePopup.form.buttons", {widget:self}));
if (this.options.alternative_form_view) {
this.view_form.set_embedded_view(this.options.alternative_form_view);
}
- this.view_form.appendTo(this.$element.find("#" + this.element_id + "_view_form"));
+ this.view_form.appendTo(this.$element.find(".oe-form-open-popup-form-view"));
this.view_form.on_loaded.add_last(function() {
var $buttons = self.view_form.$element.find(".oe_form_buttons");
$buttons.html(QWeb.render("FormOpenPopup.form.buttons"));
}
});
-openerp.web.form.FieldReference = openerp.web.form.AbstractField.extend({
+openerp.web.form.FieldReference = openerp.web.form.AbstractField.extend(_.extend({}, openerp.web.form.ReinitializeFieldMixin, {
template: 'FieldReference',
init: function(view, node) {
this._super(view, node);
this.get_selected_ids = view.get_selected_ids;
this.do_onchange = this.on_form_changed = this.do_notify_change = this.on_nop;
this.dataset = this.view.dataset;
- this.widgets_counter = 0;
this.view_id = 'reference_' + _.uniqueId();
- this.widgets = {};
this.fields = {};
this.fields_order = [];
- this.selection = new openerp.web.form.FieldSelection(this, { attrs: {
- name: 'selection',
- widget: 'selection'
- }});
this.reference_ready = true;
- this.selection.on_value_changed.add_last(this.on_selection_changed);
- this.m2o = new openerp.web.form.FieldMany2One(this, { attrs: {
- name: 'm2o',
- widget: 'many2one'
- }});
- this.m2o.on_ui_change.add_last(this.on_ui_change);
},
on_nop: function() {
},
this.m2o.$element.toggle(sel !== false);
}
},
- start: function() {
- this._super();
- // TODO: not niv compliant
- this.selection.$element = $(".oe_form_view_reference_selection", this.$element);
- this.selection.renderElement();
- this.selection.start();
+ destroy_content: function() {
+ if (this.selection) {
+ this.selection.destroy();
+ this.selection = undefined;
+ }
+ if (this.m2o) {
+ this.m2o.destroy();
+ this.m2o.undefined;
+ }
+ },
+ initialize_content: function() {
+ if (!this.get("effective_readonly")) {
+ this.selection = new openerp.web.form.FieldSelection(this, { attrs: {
+ name: 'selection',
+ widget: 'selection'
+ }});
+ this.selection.on_value_changed.add_last(this.on_selection_changed);
+
+ this.selection.$element = $(".oe_form_view_reference_selection", this.$element);
+ this.selection.renderElement();
+ this.selection.start();
+ }
+ this.m2o = new openerp.web.form.FieldMany2One(this, { attrs: {
+ name: 'm2o',
+ widget: 'many2one'
+ }});
+ this.m2o.set({"readonly": this.get("effective_readonly")});
+ this.m2o.on_ui_change.add_last(this.on_ui_change);
this.m2o.$element = $(".oe_form_view_reference_m2o", this.$element);
this.m2o.renderElement();
this.m2o.start();
},
set_value: function(value) {
this._super(value);
+ this.render_value();
+ },
+ render_value: function() {
this.reference_ready = false;
var vals = [], sel_val, m2o_val;
- if (typeof(value) === 'string') {
- vals = value.split(',');
+ if (typeof(this.value) === 'string') {
+ vals = this.value.split(',');
}
sel_val = vals[0] || false;
m2o_val = vals[1] ? parseInt(vals[1], 10) : false;
- this.selection.set_value(sel_val);
+ if (!this.get("effective_readonly")) {
+ this.selection.set_value(sel_val);
+ }
this.m2o.field.relation = sel_val;
this.m2o.set_value(m2o_val);
this.m2o.$element.toggle(sel_val !== false);
return false;
}
}
-});
+}));
-openerp.web.form.FieldBinary = openerp.web.form.AbstractField.extend({
+openerp.web.form.FieldBinary = openerp.web.form.AbstractField.extend(_.extend({}, openerp.web.form.ReinitializeFieldMixin, {
init: function(view, node) {
this._super(view, node);
this.iframe = this.element_id + '_iframe';
this.binary_value = false;
},
- start: function() {
- this._super.apply(this, arguments);
+ initialize_content: function() {
this.$element.find('input.oe-binary-file').change(this.on_file_change);
this.$element.find('button.oe-binary-file-save').click(this.on_save_as);
this.$element.find('.oe-binary-file-clear').click(this.on_clear);
}
return false;
}
-});
+}));
openerp.web.form.FieldBinaryFile = openerp.web.form.FieldBinary.extend({
template: 'FieldBinaryFile',
- update_dom: function() {
- this._super.apply(this, arguments);
- this.$element.find('.oe-binary-file-set, .oe-binary-file-clear').toggle(!this.readonly);
- this.$element.find('input[type=text]').prop('readonly', this.readonly);
+ initialize_content: function() {
+ this._super();
+ if (this.get("effective_readonly")) {
+ var self = this;
+ this.$element.find('a').click(function() {
+ if (self.value) {
+ self.on_save_as();
+ }
+ return false;
+ });
+ }
},
set_value: function(value) {
this._super.apply(this, arguments);
- var show_value;
- if (this.node.attrs.filename) {
- show_value = this.view.datarecord[this.node.attrs.filename] || '';
+ this.render_value();
+ },
+ render_value: function() {
+ if (!this.get("effective_readonly")) {
+ var show_value;
+ if (this.node.attrs.filename) {
+ show_value = this.view.datarecord[this.node.attrs.filename] || '';
+ } else {
+ show_value = (this.value != null && this.value !== false) ? this.value : '';
+ }
+ this.$element.find('input').eq(0).val(show_value);
} else {
- show_value = (value != null && value !== false) ? value : '';
+ this.$element.find('a').show(!!this.value);
+ if (this.value) {
+ var show_value = _t("Download") + " " + (this.view.datarecord[this.node.attrs.filename] || '');
+ this.$element.find('a').text(show_value);
+ }
}
- this.$element.find('input').eq(0).val(show_value);
},
on_file_uploaded_and_valid: function(size, name, content_type, file_base64) {
this.value = file_base64;
openerp.web.form.FieldBinaryImage = openerp.web.form.FieldBinary.extend({
template: 'FieldBinaryImage',
- start: function() {
- this._super.apply(this, arguments);
- this.$image = this.$element.find('img.oe-binary-image');
- },
- update_dom: function() {
- this._super.apply(this, arguments);
- this.$element.find('.oe-binary').toggle(!this.readonly);
+ initialize_content: function() {
+ this._super();
+ this.$placeholder = $(".oe_form_field-binary-image-placeholder", this.$element);
+ if (!this.get("effective_readonly"))
+ this.$element.find('.oe-binary').show();
+ else
+ this.$element.find('.oe-binary').hide();
},
set_value: function(value) {
this._super.apply(this, arguments);
- this.set_image_maxwidth();
-
+ this.render_value();
+ },
+ render_value: function() {
var url;
- if (value && value.substr(0, 10).indexOf(' ') == -1) {
+ if (this.value && this.value.substr(0, 10).indexOf(' ') == -1) {
url = 'data:image/png;base64,' + this.value;
- } else {
+ } else if (this.value) {
url = '/web/binary/image?session_id=' + this.session.session_id + '&model=' +
this.view.dataset.model +'&id=' + (this.view.datarecord.id || '') + '&field=' + this.name + '&t=' + (new Date().getTime());
+ } else {
+ url = "/web/static/src/img/placeholder.png";
}
- this.$image.attr('src', url);
- },
- set_image_maxwidth: function() {
- this.$image.css('max-width', this.$element.width());
+ var rendered = QWeb.render("FieldBinaryImage-img", {widget: this, url: url});;
+ this.$placeholder.html(rendered);
},
on_file_change: function() {
- this.set_image_maxwidth();
+ this.render_value();
this._super.apply(this, arguments);
},
on_file_uploaded_and_valid: function(size, name, content_type, file_base64) {
this.value = file_base64;
this.binary_value = true;
- this.$image.attr('src', 'data:' + (content_type || 'image/png') + ';base64,' + file_base64);
+ this.render_value();
},
on_clear: function() {
this._super.apply(this, arguments);
- this.$image.attr('src', '/web/static/src/img/placeholder.png');
+ this.render_value();
}
});