* view should be displayed (if there is one active).
*/
searchable: false,
+ readonly : false,
form_template: "FormView",
identifier_prefix: 'formview-',
/**
this.widgets = {};
this.widgets_counter = 0;
this.fields = {};
+ this.fields_order = [];
this.datarecord = {};
this.show_invalid = true;
- this.dirty_for_user = false;
this.default_focus_field = null;
this.default_focus_button = null;
this.registry = openerp.web.form.widgets;
this.has_been_loaded = $.Deferred();
this.$form_header = null;
this.translatable_fields = [];
- _.defaults(this.options, {"always_show_new_button": true,
- "not_interactible_on_create": false});
+ _.defaults(this.options, {
+ "not_interactible_on_create": false
+ });
this.mutating_lock = $.Deferred();
this.initial_mutating_lock = this.mutating_lock;
this.on_change_lock = $.Deferred().resolve();
on_loaded: function(data) {
var self = this;
if (data) {
+ this.fields_order = [];
this.fields_view = data;
var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch);
- this.rendered = QWeb.render(this.form_template, { 'frame': frame, 'view': this });
+ this.rendered = QWeb.render(this.form_template, { 'frame': frame, 'widget': this });
}
this.$element.html(this.rendered);
_.each(this.widgets, function(w) {
self.on_pager_action(action);
});
- this.$form_header.find('button.oe_form_button_save').click(this.do_save);
- this.$form_header.find('button.oe_form_button_cancel').click(this.do_cancel);
- this.$form_header.find('button.oe_form_button_new').click(this.on_button_new);
- this.$form_header.find('button.oe_form_button_duplicate').click(this.on_button_duplicate);
- this.$form_header.find('button.oe_form_button_toggle').click(function () {
- self.translatable_fields = [];
- self.widgets = {};
- self.fields = {};
- self.$form_header.find('button').unbind('click');
- self.registry = self.registry === openerp.web.form.widgets
- ? openerp.web.form.readonly
- : openerp.web.form.widgets;
- self.on_loaded(self.fields_view);
- self.reload();
- });
+ this.$form_header.find('button.oe_form_button_save').click(this.on_button_save);
+ this.$form_header.find('button.oe_form_button_cancel').click(this.on_button_cancel);
- if (this.options.sidebar && this.options.sidebar_id) {
+ if (!this.sidebar && this.options.sidebar && this.options.sidebar_id) {
this.sidebar = new openerp.web.Sidebar(this, this.options.sidebar_id);
this.sidebar.start();
this.sidebar.do_unfold();
// null index means we should start a new record
promise = this.on_button_new();
} else {
- promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
+ promise = this.dataset.read_index(_.keys(this.fields_view.fields)).pipe(this.on_record_loaded);
}
this.$element.show();
if (this.sidebar) {
}
},
on_record_loaded: function(record) {
+ var self = this,
+ deferred_stack = $.Deferred.queue();
if (!record) {
throw("Form: No record received");
}
- if (!record.id) {
- this.$form_header.find('.oe_form_on_create').show();
- this.$form_header.find('.oe_form_on_update').hide();
- if (!this.options["always_show_new_button"]) {
- this.$form_header.find('button.oe_form_button_new').hide();
- }
- } else {
- this.$form_header.find('.oe_form_on_create').hide();
- this.$form_header.find('.oe_form_on_update').show();
- this.$form_header.find('button.oe_form_button_new').show();
- }
- this.dirty_for_user = false;
this.datarecord = record;
- for (var f in this.fields) {
- var field = this.fields[f];
- field.dirty = false;
- field.set_value(this.datarecord[f] || false);
- field.validate();
- }
- if (!record.id) {
- // New record: Second pass in order to trigger the onchanges
- this.show_invalid = false;
- for (var f in record) {
- var field = this.fields[f];
- if (field) {
- field.dirty = true;
- this.do_onchange(field);
- }
+
+ _(this.fields).each(function (field, f) {
+ field.reset();
+ var result = field.set_value(self.datarecord[f] || false);
+ if (result && _.isFunction(result.promise)) {
+ deferred_stack.push(result);
}
- }
- this.on_form_changed();
- this.initial_mutating_lock.resolve();
- this.show_invalid = true;
- this.do_update_pager(record.id == null);
- if (this.sidebar) {
- this.sidebar.attachments.do_update();
- this.sidebar.$element.find('.oe_sidebar_translate').toggleClass('oe_hide', !record.id);
- }
- if (this.default_focus_field && !this.embedded_view) {
- this.default_focus_field.focus();
- }
+ $.when(result).then(function() {
+ field.validate();
+ });
+ });
+ deferred_stack.push('force resolution if no fields');
+ return deferred_stack.then(function() {
+ if (!record.id) {
+ self.show_invalid = false;
+ // New record: Second pass in order to trigger the onchanges
+ // respecting the fields order defined in the view
+ _.each(self.fields_order, function(field_name) {
+ if (record[field_name] !== undefined) {
+ var field = self.fields[field_name];
+ field.dirty = true;
+ self.do_onchange(field);
+ }
+ });
+ }
+ self.on_form_changed();
+ self.initial_mutating_lock.resolve();
+ self.show_invalid = true;
+ self.do_update_pager(record.id == null);
+ if (self.sidebar) {
+ self.sidebar.attachments.do_update();
+ }
+ if (self.default_focus_field && !self.embedded_view) {
+ self.default_focus_field.focus();
+ }
+ });
},
on_form_changed: function() {
for (var w in this.widgets) {
$pager.find('span.oe_pager_index').html(index);
$pager.find('span.oe_pager_count').html(this.dataset.ids.length);
},
+ parse_on_change: function (on_change, widget) {
+ var self = this;
+ var onchange = _.str.trim(on_change);
+ var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/);
+ if (!call) {
+ return null;
+ }
+
+ var method = call[1];
+ if (!_.str.trim(call[2])) {
+ return {method: method, args: [], context_index: null}
+ }
+
+ var argument_replacement = {
+ 'False': function () {return false;},
+ 'True': function () {return true;},
+ 'None': function () {return null;},
+ 'context': function (i) {
+ context_index = i;
+ var ctx = widget.build_context ? widget.build_context() : {};
+ return ctx;
+ }
+ };
+ var parent_fields = null, context_index = null;
+ var args = _.map(call[2].split(','), function (a, i) {
+ var field = _.str.trim(a);
+
+ // literal constant or context
+ if (field in argument_replacement) {
+ return argument_replacement[field](i);
+ }
+ // literal number
+ if (/^-?\d+(\.\d+)?$/.test(field)) {
+ return Number(field);
+ }
+ // form field
+ if (self.fields[field]) {
+ var value = self.fields[field].get_on_change_value();
+ return value == null ? false : value;
+ }
+ // parent field
+ var splitted = field.split('.');
+ if (splitted.length > 1 && _.str.trim(splitted[0]) === "parent" && self.dataset.parent_view) {
+ if (parent_fields === null) {
+ parent_fields = self.dataset.parent_view.get_fields_values();
+ }
+ var p_val = parent_fields[_.str.trim(splitted[1])];
+ if (p_val !== undefined) {
+ return p_val == null ? false : p_val;
+ }
+ }
+ // string literal
+ var first_char = field[0], last_char = field[field.length-1];
+ if ((first_char === '"' && last_char === '"')
+ || (first_char === "'" && last_char === "'")) {
+ return field.slice(1, -1);
+ }
+
+ throw new Error("Could not get field with name '" + field +
+ "' for onchange '" + onchange + "'");
+ });
+
+ return {
+ method: method,
+ args: args,
+ context_index: context_index
+ };
+ },
do_onchange: function(widget, processed) {
var self = this;
var act = function() {
try {
- processed = processed || [];
- if (widget.node.attrs.on_change) {
- var onchange = _.trim(widget.node.attrs.on_change);
- var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/);
- if (call) {
- var method = call[1], args = [];
- var context_index = null;
- var argument_replacement = {
- 'False' : function() {return false;},
- 'True' : function() {return true;},
- 'None' : function() {return null;},
- 'context': function(i) {
- context_index = i;
- var ctx = widget.build_context ? widget.build_context() : {};
- return ctx;
- }
- };
- var parent_fields = null;
- _.each(call[2].split(','), function(a, i) {
- var field = _.trim(a);
- if (field in argument_replacement) {
- args.push(argument_replacement[field](i));
- return;
- } else if (self.fields[field]) {
- var value = self.fields[field].get_on_change_value();
- args.push(value == null ? false : value);
- return;
- } else {
- var splitted = field.split('.');
- if (splitted.length > 1 && _.trim(splitted[0]) === "parent" && self.dataset.parent_view) {
- if (parent_fields === null) {
- parent_fields = self.dataset.parent_view.get_fields_values();
- }
- var p_val = parent_fields[_.trim(splitted[1])];
- if (p_val !== undefined) {
- args.push(p_val == null ? false : p_val);
- return;
- }
- }
- }
- throw "Could not get field with name '" + field +
- "' for onchange '" + onchange + "'";
- });
- var ajax = {
- url: '/web/dataset/call',
- async: false
- };
- return self.rpc(ajax, {
- model: self.dataset.model,
- method: method,
- args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(args),
- context_id: context_index === null ? null : context_index + 1
- }).pipe(function(response) {
- return self.on_processed_onchange(response, processed);
- });
- } else {
- console.log("Wrong on_change format", on_change);
+ processed = processed || [];
+ var on_change = widget.node.attrs.on_change;
+ if (on_change) {
+ var change_spec = self.parse_on_change(on_change, widget);
+ if (change_spec) {
+ var ajax = {
+ url: '/web/dataset/call',
+ async: false
+ };
+ return self.rpc(ajax, {
+ model: self.dataset.model,
+ method: change_spec.method,
+ args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(change_spec.args),
+ context_id: change_spec.context_index == undefined ? null : change_spec.context_index + 1
+ }).pipe(function(response) {
+ return self.on_processed_onchange(response, processed);
+ });
+ } else {
+ console.warn("Wrong on_change format", on_change);
+ }
}
- }
} catch(e) {
console.error(e);
return $.Deferred().reject();
processed.push(field.name);
if (field.get_value() != value) {
field.set_value(value);
- field.dirty = this.dirty_for_user = true;
+ field.dirty = true;
if (_.indexOf(processed, field.name) < 0) {
this.do_onchange(field, processed);
}
return $.Deferred().reject();
}
},
+ on_button_save: function() {
+ var self = this;
+ return this.do_save().then(function(result) {
+ self.do_prev_view(result.created);
+ });
+ },
+ on_button_cancel: function() {
+ return this.do_prev_view();
+ },
on_button_new: function() {
var self = this;
var def = $.Deferred();
if (self.can_be_discarded()) {
var keys = _.keys(self.fields_view.fields);
if (keys.length) {
- self.dataset.default_get(keys).then(self.on_record_loaded).then(function() {
+ self.dataset.default_get(keys).pipe(self.on_record_loaded).then(function() {
def.resolve();
});
} else {
- self.on_record_loaded({});
- def.resolve();
+ self.on_record_loaded({}).then(function() {
+ def.resolve();
+ });
}
}
});
return def.promise();
},
- on_button_duplicate: function() {
- var self = this;
- var def = $.Deferred();
- $.when(this.has_been_loaded).then(function() {
- if (self.can_be_discarded()) {
- self.dataset.call('copy', [self.datarecord.id, {}, self.dataset.context]).then(function(new_id) {
- return self.on_created({ result : new_id });
- }).then(function() {
- def.resolve();
- });
- }
- });
- return def.promise();
- },
can_be_discarded: function() {
- return !this.dirty_for_user || confirm(_t("Warning, the record has been modified, your changes will be discarded."));
+ return true; // FIXME: Disabled until the page view and button refactoring is done
+ return !this.is_dirty() || confirm(_t("Warning, the record has been modified, your changes will be discarded."));
},
/**
* Triggers saving the form's record. Chooses between creating a new
try {
if (!self.initial_mutating_lock.isResolved() && !self.initial_mutating_lock.isRejected())
return;
- var form_dirty = false,
- form_invalid = false,
+ var form_invalid = false,
values = {},
first_invalid_field = null;
for (var f in self.fields) {
if (!first_invalid_field) {
first_invalid_field = f;
}
- } else if (f.is_dirty()) {
- form_dirty = true;
+ } else if (f.name !== 'id' && !f.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
values[f.name] = f.get_value();
}
}
self.on_invalid();
return $.Deferred().reject();
} else {
- console.log("About to save", values);
+ var save_deferral;
if (!self.datarecord.id) {
- return self.dataset.create(values).pipe(function(r) {
+ openerp.log("FormView(", self, ") : About to create", values);
+ save_deferral = self.dataset.create(values).pipe(function(r) {
return self.on_created(r, undefined, prepend_on_create);
- }).then(success);
+ }, null);
+ } else if (_.isEmpty(values)) {
+ openerp.log("FormView(", self, ") : Nothing to save");
+ save_deferral = $.Deferred().resolve({}).promise();
} else {
- return self.dataset.write(self.datarecord.id, values, {}).pipe(function(r) {
+ openerp.log("FormView(", self, ") : About to save", values);
+ save_deferral = self.dataset.write(self.datarecord.id, values, {}).pipe(function(r) {
return self.on_saved(r);
- }).then(success);
+ }, null);
}
+ return save_deferral.then(success);
}
} catch (e) {
console.error(e);
this.mutating_lock = this.mutating_lock.pipe(action, action);
return this.mutating_lock;
},
- switch_readonly: function() {
- },
- switch_editable: function() {
- },
on_invalid: function() {
var msg = "<ul>";
_.each(this.fields, function(f) {
// should not happen in the server, but may happen for internal purpose
return $.Deferred().reject();
} else {
- this.reload();
- return $.when(r).then(success);
+ return $.when(this.reload()).pipe(function () {
+ return $.when(r).then(success); }, null);
}
},
/**
if (this.sidebar) {
this.sidebar.attachments.do_update();
}
- console.debug("The record has been created with id #" + this.datarecord.id);
+ openerp.log("The record has been created with id #" + this.datarecord.id);
this.reload();
return $.when(_.extend(r, {created: true})).then(success);
}
on_action: function (action) {
console.debug('Executing action', action);
},
- do_cancel: function () {
- console.debug("Cancelling form");
- },
reload: function() {
var self = this;
var act = function() {
if (self.dataset.index == null || self.dataset.index < 0) {
return $.when(self.on_button_new());
} else {
- return self.dataset.read_index(_.keys(self.fields_view.fields), self.on_record_loaded);
+ return self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_record_loaded);
}
};
this.reload_lock = this.reload_lock.pipe(act, act);
return self.dataset.parent_view.recursive_save();
});
},
+ is_dirty: function() {
+ return _.any(this.fields, function (value) {
+ return value.is_dirty();
+ });
+ },
is_interactible_record: function() {
var id = this.datarecord.id;
if (!id) {
return false;
}
return true;
+ },
+ sidebar_context: function () {
+ return this.do_save().pipe($.proxy(this, 'get_fields_values'));
}
});
openerp.web.FormDialog = openerp.web.Dialog.extend({
},
on_attachment_delete: function(e) {
var self = this, $e = $(e.currentTarget);
- var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
+ var name = _.str.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
if (confirm("Do you really want to delete the attachment " + name + " ?")) {
this.rpc('/web/dataset/unlink', {
model: 'ir.attachment',
stack.push(!_(val).contains(field_value));
break;
default:
- console.log("Unsupported operator in modifiers :", op);
+ console.warn("Unsupported operator in modifiers :", op);
}
}
return _.all(stack, _.identity);
this.invisible = this.modifiers['invisible'] === true;
this.classname = 'oe_form_' + this.type;
+ this.align = parseFloat(this.node.attrs.align);
+ if (isNaN(this.align) || this.align === 1) {
+ this.align = 'right';
+ } else if (this.align === 0) {
+ this.align = 'left';
+ } else {
+ this.align = 'center';
+ }
+
+
this.width = this.node.attrs.width;
},
start: function() {
var template = this.template;
return QWeb.render(template, { "widget": this });
},
+ do_attach_tooltip: function(widget, trigger, options) {
+ widget = widget || this;
+ trigger = trigger || this.$element;
+ options = _.extend({
+ delay: 1000,
+ maxWidth: openerp.connection.debug ? '300px' : '200px',
+ content: function() {
+ var template = widget.template + '.tooltip';
+ if (!QWeb.has_template(template)) {
+ template = 'WidgetLabel.tooltip';
+ }
+ return QWeb.render(template, {
+ debug: openerp.connection.debug,
+ widget: widget
+ });
+ }
+ }, options || {});
+ trigger.tipTip(options);
+ },
_build_view_fields_values: function() {
var a_dataset = this.view.dataset;
var fields_values = this.view.get_fields_values();
- var parent_values = a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {};
- fields_values.parent = parent_values;
+ var active_id = a_dataset.ids[a_dataset.index];
+ _.extend(fields_values, {
+ active_id: active_id || false,
+ active_ids: active_id ? [active_id] : [],
+ active_model: a_dataset.model,
+ parent: a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {}
+ });
return fields_values;
},
_build_eval_context: function() {
var type = {};
if (node.tag == 'field') {
type = this.view.fields_view.fields[node.attrs.name] || {};
- if (node.attrs.widget == 'statusbar') {
+ if (node.attrs.widget == 'statusbar' && node.attrs.nolabel !== '1') {
// This way we can retain backward compatibility between addons and old clients
+ node.attrs.colspan = (parseInt(node.attrs.colspan, 10) || 1) + 1;
node.attrs.nolabel = '1';
}
}
}
});
+openerp.web.form.WidgetGroup = openerp.web.form.WidgetFrame.extend({
+ template: 'WidgetGroup'
+}),
+
openerp.web.form.WidgetNotebook = openerp.web.form.Widget.extend({
template: 'WidgetNotebook',
init: function(view, node) {
});
this.$element.tabs();
this.view.on_button_new.add_first(this.do_select_first_visible_tab);
+ if (openerp.connection.debug) {
+ this.do_attach_tooltip(this, this.$element.find('ul:first'), {
+ defaultPosition: 'top'
+ });
+ }
},
do_select_first_visible_tab: function() {
for (var i = 0; i < this.pages.length; i++) {
start: function() {
this._super.apply(this, arguments);
this.$element.find("button").click(this.on_click);
+ if (this.help || openerp.connection.debug) {
+ this.do_attach_tooltip();
+ }
},
on_click: function() {
var self = this;
this.execute_action().always(function() {
self.force_disabled = false;
self.check_disable();
+ $.tipTipClear();
});
},
execute_action: function() {
this._super(view, node);
- // TODO fme: support for attrs.align
- if (this.node.tag == 'label' && (this.node.attrs.colspan || (this.string && this.string.length > 32))) {
+ if (this.node.tag == 'label' && (this.align === 'left' || this.node.attrs.colspan || (this.string && this.string.length > 32))) {
this.template = "WidgetParagraph";
this.colspan = parseInt(this.node.attrs.colspan || 1, 10);
+ // Widgets default to right-aligned, but paragraph defaults to
+ // left-aligned
+ if (isNaN(parseFloat(this.node.attrs.align))) {
+ this.align = 'left';
+ }
} else {
this.colspan = 1;
this.width = '1%';
start: function() {
this._super();
var self = this;
+ if (this['for'] && (this['for'].help || openerp.connection.debug)) {
+ this.do_attach_tooltip(self['for']);
+ }
this.$element.find("label").dblclick(function() {
var widget = self['for'] || self;
- console.log(widget.element_class , widget);
+ openerp.log(widget.element_class , widget);
window.w = widget;
});
}
this.name = node.attrs.name;
this.value = undefined;
view.fields[this.name] = this;
+ view.fields_order.push(this.name);
this.type = node.attrs.widget || view.fields_view.fields[node.attrs.name].type;
this.element_name = "field_" + this.name + "_" + this.type;
this.nolabel = (this.field.nolabel || node.attrs.nolabel) === '1';
this.readonly = this.modifiers['readonly'] === true;
this.required = this.modifiers['required'] === true;
- this.invalid = false;
- this.dirty = false;
+ this.invalid = this.dirty = false;
this.classname = 'oe_form_field_' + this.type;
},
this.view.translatable_fields.push(this);
this.$element.find('.oe_field_translate').click(this.on_translate);
}
+ if (this.nolabel && openerp.connection.debug) {
+ this.do_attach_tooltip(this, this.$element, {
+ defaultPosition: 'top'
+ });
+ }
},
set_value: function(value) {
this.value = value;
}
},
on_ui_change: function() {
- this.dirty = this.view.dirty_for_user = true;
+ this.dirty = true;
this.validate();
if (this.is_valid()) {
this.set_value_from_ui();
this.invalid = false;
},
focus: function() {
+ },
+ reset: function() {
+ this.dirty = false;
}
});
openerp.web.form.FieldChar = openerp.web.form.Field.extend({
template: 'FieldChar',
+ init: function (view, node) {
+ this._super(view, node);
+ this.password = this.node.attrs.password === 'True' || this.node.attrs.password === '1';
+ },
start: function() {
this._super.apply(this, arguments);
this.$element.find('input').change(this.on_ui_change);
if (value === false || value === undefined) {
// As in GTK client, floats default to 0
value = 0;
- this.dirty = true;
}
this._super.apply(this, [value]);
}
template: "web.datetimepicker",
jqueryui_object: 'datetimepicker',
type_of_date: "datetime",
+ init: function(parent) {
+ this._super(parent);
+ this.name = parent.name;
+ },
start: function() {
var self = this;
- this.$element.find('input').change(this.on_change);
+ this.$input = this.$element.find('input.oe_datepicker_master');
+ this.$input_picker = this.$element.find('input.oe_datepicker_container');
+ this.$input.change(this.on_change);
this.picker({
onSelect: this.on_picker_select,
changeMonth: true,
changeYear: true,
showWeek: true,
- showButtonPanel: false
+ showButtonPanel: true
});
this.$element.find('img.oe_datepicker_trigger').click(function() {
if (!self.readonly) {
self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date());
- self.$element.find('.oe_datepicker').toggle();
+ self.$input_picker.show();
+ self.picker('show');
+ self.$input_picker.hide();
}
});
- this.$element.find('.ui-datepicker-inline').removeClass('ui-widget-content ui-corner-all');
- this.$element.find('button.oe_datepicker_close').click(function() {
- self.$element.find('.oe_datepicker').hide();
- });
this.set_readonly(false);
this.value = false;
},
picker: function() {
- return $.fn[this.jqueryui_object].apply(this.$element.find('.oe_datepicker_container'), arguments);
+ return $.fn[this.jqueryui_object].apply(this.$input_picker, arguments);
},
on_picker_select: function(text, instance) {
var date = this.picker('getDate');
- this.$element.find('input').val(date ? this.format_client(date) : '').change();
+ this.$input.val(date ? this.format_client(date) : '').change();
},
set_value: function(value) {
this.value = value;
- this.$element.find('input').val(value ? this.format_client(value) : '');
+ this.$input.val(value ? this.format_client(value) : '');
},
get_value: function() {
return this.value;
},
set_value_from_ui: function() {
- var value = this.$element.find('input').val() || false;
+ var value = this.$input.val() || false;
this.value = this.parse_client(value);
},
set_readonly: function(readonly) {
this.readonly = readonly;
- this.$element.find('input').attr('disabled', this.readonly);
+ this.$input.attr('disabled', this.readonly);
this.$element.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly);
},
is_valid: function(required) {
- var value = this.$element.find('input').val();
+ var value = this.$input.val();
if (value === "") {
return !required;
} else {
}
},
focus: function() {
- this.$element.find('input').focus();
+ this.$input.focus();
},
parse_client: function(v) {
return openerp.web.parse_value(v, {"widget": this.type_of_date});
openerp.web.DateWidget = openerp.web.DateTimeWidget.extend({
jqueryui_object: 'datepicker',
- type_of_date: "date",
- on_picker_select: function(text, instance) {
- this._super(text, instance);
- this.$element.find('.oe_datepicker').hide();
- }
+ type_of_date: "date"
});
openerp.web.form.FieldDatetime = openerp.web.form.Field.extend({
var self = this;
this._super.apply(this, arguments);
this.datewidget = this.build_widget();
- this.datewidget.on_change.add(this.on_ui_change);
+ this.datewidget.on_change.add_last(this.on_ui_change);
this.datewidget.appendTo(this.$element);
},
set_value: function(value) {
init: function(view, node) {
var self = this;
this._super(view, node);
- this.values = this.field.selection;
+ this.values = _.clone(this.field.selection);
_.each(this.values, function(v, i) {
if (v[0] === false && v[1] === '') {
self.values.splice(i, 1);
if (search_val.length > 0 &&
!_.include(raw_result, search_val) &&
(!self.value || search_val !== self.value[1])) {
- values.push({label: _.sprintf(_t('<em>Â Â Â Create "<strong>%s</strong>"</em>'),
+ values.push({label: _.str.sprintf(_t('<em>Â Â Â Create "<strong>%s</strong>"</em>'),
$('<span />').text(search_val).html()), action: function() {
self._quick_create(search_val);
}});
self.original_value = undefined;
self._change_int_ext_value(rval);
};
- if(typeof(value) === "number") {
+ if (value && !(value instanceof Array)) {
var dataset = new openerp.web.DataSetStatic(this, this.field.relation, self.build_context());
dataset.name_get([value], function(data) {
real_set_value(data[0]);
multi_selection: false,
init: function(view, node) {
this._super(view, node);
- this.is_started = $.Deferred();
+ this.is_loaded = $.Deferred();
+ this.initial_is_loaded = this.is_loaded;
this.is_setted = $.Deferred();
this.form_last_update = $.Deferred();
this.init_form_last_update = this.form_last_update;
self.on_ui_change();
});
+ this.is_setted.then(function() {
+ self.load_views();
+ });
+ },
+ is_readonly: function() {
+ return this.readonly || this.force_readonly;
+ },
+ load_views: function() {
+ var self = this;
+
var modes = this.node.attrs.mode;
- modes = !!modes ? modes.split(",") : ["tree", "form"];
+ modes = !!modes ? modes.split(",") : ["tree"];
var views = [];
_.each(modes, function(mode) {
var view = {
}
if(view.view_type === "list") {
view.options.selectable = self.multi_selection;
+ if (self.is_readonly()) {
+ view.options.addable = null;
+ view.options.deletable = null;
+ }
} else if (view.view_type === "form") {
+ if (self.is_readonly()) {
+ view.view_type = 'page';
+ }
view.options.not_interactible_on_create = true;
}
views.push(view);
this.views = views;
this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views);
+ this.viewmanager.template = 'One2Many.viewmanager';
this.viewmanager.registry = openerp.web.views.clone({
list: 'openerp.web.form.One2ManyListView',
- form: 'openerp.web.form.One2ManyFormView'
+ form: 'openerp.web.FormView',
+ page: 'openerp.web.PageView'
});
var once = $.Deferred().then(function() {
self.init_form_last_update.resolve();
});
+ var def = $.Deferred().then(function() {
+ self.initial_is_loaded.resolve();
+ });
this.viewmanager.on_controller_inited.add_last(function(view_type, controller) {
if (view_type == "list") {
controller.o2m = self;
- } else if (view_type == "form") {
+ if (self.is_readonly())
+ controller.set_editable(false);
+ } else if (view_type == "form" || view_type == 'page') {
+ if (view_type == 'page') {
+ controller.$element.find(".oe_form_buttons").hide();
+ }
controller.on_record_loaded.add_last(function() {
once.resolve();
});
controller.on_pager_action.add_first(function() {
- self.save_form_view();
+ self.save_any_view();
});
controller.$element.find(".oe_form_button_save").hide();
} else if (view_type == "graph") {
self.reload_current_view()
}
- self.is_started.resolve();
+ def.resolve();
});
- this.viewmanager.on_mode_switch.add_first(function() {
- self.save_form_view();
+ this.viewmanager.on_mode_switch.add_first(function(n_mode, b, c, d, e) {
+ $.when(self.save_any_view()).then(function() {
+ if(n_mode === "list")
+ setTimeout(function() {self.reload_current_view();}, 0);
+ });
});
this.is_setted.then(function() {
setTimeout(function () {
self.viewmanager.appendTo(self.$element);
}, 0);
});
+ return def;
},
reload_current_view: function() {
var self = this;
- var view = self.viewmanager.views[self.viewmanager.active_view].controller;
- if(self.viewmanager.active_view === "list") {
- view.reload_content();
- } else if (self.viewmanager.active_view === "form") {
- if (this.dataset.index === null && this.dataset.ids.length >= 1) {
- this.dataset.index = 0;
- }
- var act = function() {
- return view.do_show();
+ return self.is_loaded = self.is_loaded.pipe(function() {
+ var active_view = self.viewmanager.active_view;
+ var view = self.viewmanager.views[active_view].controller;
+ if(active_view === "list") {
+ return view.reload_content();
+ } else if (active_view === "form" || active_view === 'page') {
+ if (self.dataset.index === null && self.dataset.ids.length >= 1) {
+ self.dataset.index = 0;
+ }
+ var act = function() {
+ return view.do_show();
+ };
+ self.form_last_update = self.form_last_update.pipe(act, act);
+ return self.form_last_update;
+ } else if (active_view === "graph") {
+ return view.do_search(self.build_domain(), self.dataset.get_context(), []);
}
- this.form_last_update = this.form_last_update.pipe(act, act);;
- } else if (self.viewmanager.active_view === "graph") {
- view.do_search(this.build_domain(), this.dataset.get_context(), []);
- }
+ }, undefined);
},
set_value: function(value) {
value = value || [];
if (this.dataset.index === null && this.dataset.ids.length > 0) {
this.dataset.index = 0;
}
- $.when(this.is_started).then(function() {
- self.reload_current_view();
- });
- this.is_setted.resolve();
+ self.is_setted.resolve();
+ return self.reload_current_view();
},
get_value: function() {
var self = this;
if (!this.dataset)
return [];
+ this.save_any_view();
var val = this.dataset.delete_all ? [commands.delete_all()] : [];
val = val.concat(_.map(this.dataset.ids, function(id) {
var alter_order = _.detect(self.dataset.to_create, function(x) {return x.id === id;});
this.dataset.to_delete, function(x) {
return commands['delete'](x.id);}));
},
- save_form_view: function() {
+ save_any_view: function() {
if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view &&
this.viewmanager.views[this.viewmanager.active_view] &&
this.viewmanager.views[this.viewmanager.active_view].controller) {
console.warn("Asynchronous get_value() is not supported in form view.");
}*/
return res;
+ } else if (this.viewmanager.active_view === "list") {
+ var res = $.when(view.ensure_saved());
+ // it seems line there are some cases when this happens
+ /*if (!res.isResolved() && !res.isRejected()) {
+ console.warn("Asynchronous get_value() is not supported in list view.");
+ }*/
+ return res;
}
}
return false;
}
},
is_dirty: function() {
- this.save_form_view();
+ this.save_any_view();
return this._super();
},
update_dom: function() {
this._super.apply(this, arguments);
- this.$element.toggleClass('disabled', this.readonly);
+ var self = this;
+ if (this.previous_readonly !== this.readonly) {
+ this.previous_readonly = this.readonly;
+ if (this.viewmanager) {
+ this.is_loaded = this.is_loaded.pipe(function() {
+ self.viewmanager.stop();
+ return $.when(self.load_views()).then(function() {
+ self.reload_current_view();
+ });
+ });
+ }
+ }
}
});
}
});
-openerp.web.form.One2ManyFormView = openerp.web.FormView.extend({
-});
-
openerp.web.form.One2ManyListView = openerp.web.ListView.extend({
+ _template: 'One2Many.listview',
do_add_record: function () {
if (this.options.editable) {
this._super.apply(this, arguments);
read_function: function() {
return self.o2m.dataset.read_ids.apply(self.o2m.dataset, arguments);
},
- form_view_options: {'not_interactible_on_create':true}
+ form_view_options: {'not_interactible_on_create':true},
+ readonly: self.o2m.is_readonly()
});
pop.on_write.add(function(id, data) {
self.o2m.dataset.write(id, data, {}, function(r) {
init: function(view, node) {
this._super(view, node);
this.list_id = _.uniqueId("many2many");
- this.is_started = $.Deferred();
+ this.is_loaded = $.Deferred();
+ this.initial_is_loaded = this.is_loaded;
+ this.is_setted = $.Deferred();
},
start: function() {
this._super.apply(this, arguments);
this.dataset.on_unlink.add_last(function(ids) {
self.on_ui_change();
});
-
- this.list_view = new openerp.web.form.Many2ManyListView(this, this.dataset, false, {
- 'addable': 'Add',
- 'selectable': self.multi_selection
- });
- this.list_view.m2m_field = this;
- this.list_view.on_loaded.add_last(function() {
- self.is_started.resolve();
+
+ this.is_setted.then(function() {
+ self.load_view();
});
- setTimeout(function () {
- self.list_view.appendTo($("#" + self.list_id));
- }, 0);
},
set_value: function(value) {
value = value || [];
this._super(value);
this.dataset.set_ids(value);
var self = this;
- $.when(this.is_started).then(function() {
- self.list_view.reload_content();
- });
+ self.reload_content();
+ this.is_setted.resolve();
},
get_value: function() {
return [commands.replace_with(this.dataset.ids)];
},
validate: function() {
this.invalid = false;
- // TODO niv
+ },
+ is_readonly: function() {
+ return this.readonly || this.force_readonly;
+ },
+ load_view: function() {
+ var self = this;
+ this.list_view = new openerp.web.form.Many2ManyListView(this, this.dataset, false, {
+ 'addable': self.is_readonly() ? null : 'Add',
+ 'deletable': self.is_readonly() ? false : true,
+ 'selectable': self.multi_selection
+ });
+ var embedded = (this.field.views || {}).tree;
+ if (embedded) {
+ this.list_view.set_embedded_view(embedded);
+ }
+ this.list_view.m2m_field = this;
+ var loaded = $.Deferred();
+ this.list_view.on_loaded.add_last(function() {
+ self.initial_is_loaded.resolve();
+ loaded.resolve();
+ });
+ setTimeout(function () {
+ self.list_view.appendTo($("#" + self.list_id));
+ }, 0);
+ return loaded;
+ },
+ reload_content: function() {
+ var self = this;
+ this.is_loaded = this.is_loaded.pipe(function() {
+ return self.list_view.reload_content();
+ });
+ },
+ update_dom: function() {
+ this._super.apply(this, arguments);
+ var self = this;
+ if (this.previous_readonly !== this.readonly) {
+ this.previous_readonly = this.readonly;
+ if (this.list_view) {
+ this.is_loaded = this.is_loaded.pipe(function() {
+ self.list_view.stop();
+ return $.when(self.load_view()).then(function() {
+ self.reload_content();
+ });
+ });
+ }
+ }
}
});
do_activate_record: function(index, id) {
var self = this;
var pop = new openerp.web.form.FormOpenPopup(this);
- pop.show_element(this.dataset.model, id, this.m2m_field.build_context(), {});
+ pop.show_element(this.dataset.model, id, this.m2m_field.build_context(), {
+ readonly: this.widget_parent.is_readonly()
+ });
pop.on_write_completed.add_last(function() {
self.reload_content();
});
}, read_function: null});
this.initial_ids = this.options.initial_ids;
this.created_elements = [];
- openerp.web.form.dialog(this.render(), {close:function() {
+ this.render_element();
+ openerp.web.form.dialog(this.$element, {close:function() {
self.check_exit();
}});
this.start();
this.dataset.parent_view = this.options.parent_view;
this.dataset.on_default_get.add(this.on_default_get);
if (this.options.initial_view == "search") {
- this.setup_search_view();
+ self.rpc('/web/session/eval_domain_and_context', {
+ domains: [],
+ contexts: [this.context]
+ }, function (results) {
+ var search_defaults = {};
+ _.each(results.context, function (value, key) {
+ var match = /^search_default_(.*)$/.exec(key);
+ if (match) {
+ search_defaults[match[1]] = value;
+ }
+ });
+ self.setup_search_view(search_defaults);
+ });
} else { // "form"
this.new_object();
}
},
- setup_search_view: function() {
+ setup_search_view: function(search_defaults) {
var self = this;
if (this.searchview) {
this.searchview.stop();
}
this.searchview = new openerp.web.SearchView(this,
- this.dataset, false, {
- "selectable": !this.options.disable_multiple_selection,
- "deletable": false
- });
+ this.dataset, false, search_defaults);
this.searchview.on_search.add(function(domains, contexts, groupbys) {
if (self.initial_ids) {
self.do_search(domains.concat([[["id", "in", self.initial_ids]], self.domain]),
});
self.view_list = new openerp.web.form.SelectCreateListView(self,
self.dataset, false,
- _.extend({'deletable': false}, self.options.list_view_options || {}));
+ _.extend({'deletable': false,
+ '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.do_show();
* - read_function
* - parent_view
* - form_view_options
+ * - readonly
*/
show_element: function(model, row_id, context, options) {
this.model = model;
this.row_id = row_id;
this.context = context || {};
this.options = _.defaults(options || {}, {"auto_write": true});
- jQuery(this.render()).dialog({title: '',
+ this.render_element();
+ this.$element.dialog({title: '',
modal: true,
width: 960,
height: 600});
on_write_completed: function() {},
setup_form_view: function() {
var self = this;
- this.view_form = new openerp.web.FormView(this, this.dataset, false, self.options.form_view_options);
+ var FormClass = this.options.readonly
+ ? openerp.web.views.get_object('page')
+ : openerp.web.views.get_object('form');
+ this.view_form = new FormClass(this, this.dataset, false, self.options.form_view_options);
if (this.options.alternative_form_view) {
this.view_form.set_embedded_view(this.options.alternative_form_view);
}
$cbutton.click(function() {
self.stop();
});
+ if (self.options.readonly) {
+ $nbutton.hide();
+ $cbutton.text(_t("Close"));
+ }
self.view_form.do_show();
});
this.dataset.on_write.add(this.on_write);
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',
on_nop: function() {
},
on_selection_changed: function() {
- var sel = this.selection.get_value();
- this.m2o.field.relation = sel;
- this.m2o.set_value(null);
- this.m2o.$element.toggle(sel !== false);
+ if (this.reference_ready) {
+ var sel = this.selection.get_value();
+ this.m2o.field.relation = sel;
+ this.m2o.set_value(null);
+ this.m2o.$element.toggle(sel !== false);
+ }
},
start: function() {
this._super();
},
set_value: function(value) {
this._super(value);
+ this.reference_ready = false;
+ var vals = [], sel_val, m2o_val;
if (typeof(value) === 'string') {
- var vals = value.split(',');
- this.selection.set_value(vals[0]);
- this.m2o.set_value(parseInt(vals[1], 10));
+ vals = value.split(',');
}
+ sel_val = vals[0] || false;
+ m2o_val = vals[1] ? parseInt(vals[1], 10) : false;
+ 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);
+ this.reference_ready = true;
},
get_value: function() {
var model = this.selection.get_value(),
render_list: function() {
var self = this;
var shown = _.map(((this.node.attrs || {}).statusbar_visible || "").split(","),
- function(x) { return _.trim(x); });
+ function(x) { return _.str.trim(x); });
shown = _.select(shown, function(x) { return x.length > 0; });
if (shown.length == 0) {
}
});
-openerp.web.form.FieldReadonly = openerp.web.form.Field.extend({
-});
-openerp.web.form.FieldCharReadonly = openerp.web.form.FieldReadonly.extend({
- template: 'FieldChar.readonly',
- set_value: function (value) {
- this._super.apply(this, arguments);
- var show_value = openerp.web.format_value(value, this, '');
- this.$element.find('div').text(show_value);
- return show_value;
- }
-});
-openerp.web.form.FieldURIReadonly = openerp.web.form.FieldCharReadonly.extend({
- template: 'FieldURI.readonly',
- scheme: null,
- set_value: function (value) {
- var displayed = this._super.apply(this, arguments);
- this.$element.find('a')
- .attr('href', this.scheme + ':' + displayed)
- .text(displayed);
- }
-});
-openerp.web.form.FieldEmailReadonly = openerp.web.form.FieldURIReadonly.extend({
- scheme: 'mailto'
-});
-openerp.web.form.FieldUrlReadonly = openerp.web.form.FieldURIReadonly.extend({
- set_value: function (value) {
- var s = /(\w+):(.+)/.exec(value);
- if (!s || !(s[1] === 'http' || s[1] === 'https')) { return; }
- this.scheme = s[1];
- this._super(s[2]);
- }
-});
-openerp.web.form.FieldBooleanReadonly = openerp.web.form.FieldCharReadonly.extend({
- set_value: function (value) {
- this._super(value ? '\u2611' : '\u2610');
- }
-});
-openerp.web.form.FieldSelectionReadonly = openerp.web.form.FieldReadonly.extend({
- template: 'FieldChar.readonly',
- init: function(view, node) {
- // lifted straight from r/w version
- var self = this;
- this._super(view, node);
- this.values = this.field.selection;
- _.each(this.values, function(v, i) {
- if (v[0] === false && v[1] === '') {
- self.values.splice(i, 1);
- }
- });
- this.values.unshift([false, '']);
- },
- set_value: function (value) {
- value = value === null ? false : value;
- value = value instanceof Array ? value[0] : value;
- var option = _(this.values)
- .detect(function (record) { return record[0] === value; });
- this._super(value);
- this.$element.find('div').text(option ? option[1] : this.values[0][1]);
- }
-});
-openerp.web.form.FieldMany2OneReadonly = openerp.web.form.FieldCharReadonly.extend({
- set_value: function (value) {
- value = value || null;
- this.invalid = false;
- var self = this;
- this.value = value;
- self.update_dom();
- self.on_value_changed();
- var real_set_value = function(rval) {
- self.$element.find('div').text(rval ? rval[1] : '');
- };
- if(typeof(value) === "number") {
- var dataset = new openerp.web.DataSetStatic(
- this, this.field.relation, self.build_context());
- dataset.name_get([value], function(data) {
- real_set_value(data[0]);
- }).fail(function() {self.tmp_value = undefined;});
- } else {
- setTimeout(function() {real_set_value(value);}, 0);
- }
- }
-});
/**
* Registry of form widgets, called by :js:`openerp.web.FormView`
*/
openerp.web.form.widgets = new openerp.web.Registry({
'frame' : 'openerp.web.form.WidgetFrame',
- 'group' : 'openerp.web.form.WidgetFrame',
+ 'group' : 'openerp.web.form.WidgetGroup',
'notebook' : 'openerp.web.form.WidgetNotebook',
'notebookpage' : 'openerp.web.form.WidgetNotebookPage',
'separator' : 'openerp.web.form.WidgetSeparator',
'binary': 'openerp.web.form.FieldBinaryFile',
'statusbar': 'openerp.web.form.FieldStatus'
});
-openerp.web.form.readonly = openerp.web.form.widgets.clone({
- 'char': 'openerp.web.form.FieldCharReadonly',
- 'email': 'openerp.web.form.FieldEmailReadonly',
- 'url': 'openerp.web.form.FieldUrlReadonly',
- 'text': 'openerp.web.form.FieldCharReadonly',
- 'text_wiki' : 'openerp.web.form.FieldCharReadonly',
- 'date': 'openerp.web.form.FieldCharReadonly',
- 'datetime': 'openerp.web.form.FieldCharReadonly',
- 'selection' : 'openerp.web.form.FieldSelectionReadonly',
- 'many2one': 'openerp.web.form.FieldMany2OneReadonly',
- 'boolean': 'openerp.web.form.FieldBooleanReadonly',
- 'float': 'openerp.web.form.FieldCharReadonly',
- 'integer': 'openerp.web.form.FieldCharReadonly',
- 'float_time': 'openerp.web.form.FieldCharReadonly'
-});
+
};