}
});
+instance.web.form.FieldRadio = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
+ template: 'FieldRadio',
+ events: {
+ 'click input': 'click_change_value'
+ },
+ init: function(field_manager, node) {
+ /* Radio button widget: Attributes options:
+ * - "horizontal" to display in column
+ * - "no_radiolabel" don't display text values
+ */
+ this._super(field_manager, node);
+ this.selection = _.clone(this.field.selection) || [];
+ this.domain = false;
+ },
+ initialize_content: function () {
+ this.uniqueId = _.uniqueId("radio");
+ this.on("change:effective_readonly", this, this.render_value);
+ this.field_manager.on("view_content_has_changed", this, this.get_selection);
+ this.get_selection();
+ },
+ click_change_value: function (event) {
+ var val = $(event.target).val();
+ val = this.field.type == "selection" ? val : +val;
+ if (val == this.get_value()) {
+ this.set_value(false);
+ } else {
+ this.set_value(val);
+ }
+ },
+ /** Get the selection and render it
+ * selection: [[identifier, value_to_display], ...]
+ * For selection fields: this is directly given by this.field.selection
+ * For many2one fields: perform a search on the relation of the many2one field
+ */
+ get_selection: function() {
+ var self = this;
+ var selection = [];
+ var def = $.Deferred();
+ if (self.field.type == "many2one") {
+ var domain = instance.web.pyeval.eval('domain', this.build_domain()) || [];
+ if (! _.isEqual(self.domain, domain)) {
+ self.domain = domain;
+ var ds = new instance.web.DataSetStatic(self, self.field.relation, self.build_context());
+ ds.call('search', [self.domain])
+ .then(function (records) {
+ ds.name_get(records).then(function (records) {
+ selection = records;
+ def.resolve();
+ });
+ });
+ } else {
+ selection = self.selection;
+ def.resolve();
+ }
+ }
+ else if (self.field.type == "selection") {
+ selection = self.field.selection || [];
+ def.resolve();
+ }
+ return def.then(function () {
+ if (! _.isEqual(selection, self.selection)) {
+ self.selection = _.clone(selection);
+ self.renderElement();
+ self.render_value();
+ }
+ });
+ },
+ set_value: function (value_) {
+ if (value_) {
+ if (this.field.type == "selection") {
+ value_ = _.find(this.field.selection, function (sel) { return sel[0] == value_});
+ }
+ else if (!this.selection.length) {
+ this.selection = [value_];
+ }
+ }
+ this._super(value_);
+ },
+ get_value: function () {
+ var value = this.get('value');
+ return value instanceof Array ? value[0] : value;
+ },
+ render_value: function () {
+ var self = this;
+ this.$el.toggleClass("oe_readonly", this.get('effective_readonly'));
+ this.$("input:checked").prop("checked", false);
+ if (this.get_value()) {
+ 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] : "");
+ }
+ }
+});
+
// jquery autocomplete tweak to allow html and classnames
(function() {
var proto = $.ui.autocomplete.prototype,
instance.web.form.CompletionFieldMixin.init.call(this);
this.set({'value': false});
this.display_value = {};
+ this.display_value_backup = {};
this.last_search = [];
this.floating = false;
this.current_display = null;
);
pop.on('write_completed', self, function(){
self.display_value = {};
+ self.display_value_backup = {};
self.render_value();
self.focus();
self.view.do_onchange(self);
this.$input.keydown(input_changed);
this.$input.change(input_changed);
this.$drop_down.click(function() {
+ self.$input.focus();
if (self.$input.autocomplete("widget").is(":visible")) {
- self.$input.autocomplete("close");
- self.$input.focus();
+ self.$input.autocomplete("close");
} else {
if (self.get("value") && ! self.floating) {
self.$input.autocomplete("search", "");
if (self.last_search.length > 0) {
if (self.last_search[0][0] != self.get("value")) {
self.display_value = {};
+ self.display_value_backup = {};
self.display_value["" + self.last_search[0][0]] = self.last_search[0][1];
self.reinit_value(self.last_search[0][0]);
} else {
var item = ui.item;
if (item.id) {
self.display_value = {};
+ self.display_value_backup = {};
self.display_value["" + item.id] = item.name;
self.reinit_value(item.id);
} else if (item.action) {
this.alive(dataset.name_get([self.get("value")])).done(function(data) {
self.display_value["" + self.get("value")] = data[0][1];
self.render_value(true);
+ }).fail( function (data, event) {
+ // avoid displaying crash errors as many2One should be name_get compliant
+ event.preventDefault();
+ self.display_value["" + self.get("value")] = self.display_value_backup["" + self.get("value")];
+ self.render_value(true);
});
}
},
var self = this;
if (value_ instanceof Array) {
this.display_value = {};
+ this.display_value_backup = {}
if (! this.options.always_reload) {
this.display_value["" + value_[0]] = value_[1];
}
+ else {
+ this.display_value_backup["" + value_[0]] = value_[1];
+ }
value_ = value_[0];
}
value_ = value_ || false;
},
add_id: function(id) {
this.display_value = {};
+ this.display_value_backup = {};
this.reinit_value(id);
},
is_false: function() {
var input = this.$text && this.$text[0];
return input ? input.focus() : false;
},
+ set_dimensions: function (height, width) {
+ this._super(height, width);
+ this.$("textarea").css({
+ width: width,
+ minHeight: height
+ });
+ },
});
/**
});
/**
- * Widget for (one2many field) to upload one or more file in same time and display in list.
+ * Widget for (many2many field) to upload one or more file in same time and display in list.
* The user can delete his files.
* Options on attribute ; "blockui" {Boolean} block the UI or not
* during the file is uploading
if(this.field.type != "many2many" || this.field.relation != 'ir.attachment') {
throw _.str.sprintf(_t("The type of the field '%s' must be a many2many field with a relation to 'ir.attachment' model."), this.field.string);
}
+ this.data = {};
+ this.set_value([]);
this.ds_file = new instance.web.DataSetSearch(this, 'ir.attachment');
this.fileupload_id = _.uniqueId('oe_fileupload_temp');
$(window).on(this.fileupload_id, _.bind(this.on_file_loaded, this));
this.$el.on('change', 'input.oe_form_binary_file', this.on_file_change );
},
set_value: function(value_) {
- var value_ = value_ || [];
- var self = this;
- var ids = [];
- _.each(value_, function(command) {
- if (isNaN(command) && command.id == undefined) {
- switch (command[0]) {
- case commands.CREATE:
- ids = ids.concat(command[2]);
- return;
- case commands.REPLACE_WITH:
- ids = ids.concat(command[2]);
- return;
- case commands.UPDATE:
- ids = ids.concat(command[2]);
- return;
- case commands.LINK_TO:
- ids = ids.concat(command[1]);
- return;
- case commands.DELETE:
- ids = _.filter(ids, function (id) { return id != command[1];});
- return;
- case commands.DELETE_ALL:
- ids = [];
- return;
- }
- } else {
- ids.push(command);
- }
- });
- this._super( ids );
+ value_ = value_ || [];
+ if (value_.length >= 1 && value_[0] instanceof Array) {
+ value_ = value_[0][2];
+ }
+ this._super(value_);
},
get_value: function() {
- return _.map(this.get('value'), function (value) { return commands.link_to( isNaN(value) ? value.id : value ); });
+ var tmp = [commands.replace_with(this.get("value"))];
+ return tmp;
},
get_file_url: function (attachment) {
return this.session.url('/web/binary/saveas', {model: 'ir.attachment', field: 'datas', filename_field: 'datas_fname', id: attachment['id']});
},
read_name_values : function () {
var self = this;
- // select the list of id for a get_name
- var values = [];
- _.each(this.get('value'), function (val) {
- if (typeof val != 'object') {
- values.push(val);
- }
- });
+ // don't reset know values
+ var _value = _.filter(this.get('value'), function (id) { return typeof self.data[id] == 'undefined'; } );
// send request for get_name
- if (values.length) {
- return this.ds_file.call('read', [values, ['id', 'name', 'datas_fname']]).done(function (datas) {
+ if (_value.length) {
+ return this.ds_file.call('read', [_value, ['id', 'name', 'datas_fname']]).done(function (datas) {
_.each(datas, function (data) {
data.no_unlink = true;
data.url = self.session.url('/web/binary/saveas', {model: 'ir.attachment', field: 'datas', filename_field: 'datas_fname', id: data.id});
-
- _.each(self.get('value'), function (val, key) {
- if(val == data.id) {
- self.get('value')[key] = data;
- }
- });
+ self.data[data.id] = data;
});
});
} else {
- return $.when(this.get('value'));
+ return $.when();
}
},
render_value: function () {
var self = this;
- this.read_name_values().then(function (datas) {
+ this.read_name_values().then(function () {
var render = $(instance.web.qweb.render('FieldBinaryFileUploader.files', {'widget': self}));
render.on('click', '.oe_delete', _.bind(self.on_file_delete, self));
var self = this;
var $target = $(event.target);
if ($target.val() !== '') {
-
var filename = $target.val().replace(/.*[\\\/]/,'');
-
- // if the files is currently uploded, don't send again
- if( !isNaN(_.find(this.get('value'), function (file) { return (file.filename || file.name) == filename && file.upload; } )) ) {
+ // don't uplode more of one file in same time
+ if (self.data[0] && self.data[0].upload ) {
return false;
}
+ for (var id in this.get('value')) {
+ // if the files exits, delete the file before upload (if it's a new file)
+ if (self.data[id] && (self.data[id].filename || self.data[id].name) == filename && !self.data[id].no_unlink ) {
+ self.ds_file.unlink([id]);
+ }
+ }
// block UI or not
if(this.node.attrs.blockui>0) {
instance.web.blockUI();
}
- // if the files exits for this answer, delete the file before upload
- var files = _.filter(this.get('value'), function (file) {
- if((file.filename || file.name) == filename) {
- self.ds_file.unlink([file.id]);
- return false;
- } else {
- return true;
- }
- });
-
// TODO : unactivate send on wizard and form
// submit file
this.$('form.oe_form_binary_form').submit();
this.$(".oe_fileupload").hide();
-
- // add file on result
- files.push({
+ // add file on data result
+ this.data[0] = {
'id': 0,
'name': filename,
'filename': filename,
'url': '',
'upload': true
- });
-
- this.set({'value': files});
+ };
}
},
on_file_loaded: function (event, result) {
instance.web.unblockUI();
}
- // TODO : activate send on wizard and form
-
if (result.error || !result.id ) {
this.do_warn( _t('Uploading Error'), result.error);
- files = _.filter(files, function (val) { return !val.upload; });
+ delete this.data[0];
} else {
- for(var i in files){
- if(files[i].filename == result.filename && files[i].upload) {
- files[i] = {
- 'id': result.id,
- 'name': result.name,
- 'filename': result.filename,
- 'url': this.get_file_url(result)
- };
- }
+ if (this.data[0] && this.data[0].filename == result.filename && this.data[0].upload) {
+ delete this.data[0];
+ this.data[result.id] = {
+ 'id': result.id,
+ 'name': result.name,
+ 'filename': result.filename,
+ 'url': this.get_file_url(result)
+ };
+ } else {
+ this.data[result.id] = {
+ 'id': result.id,
+ 'name': result.name,
+ 'filename': result.filename,
+ 'url': this.get_file_url(result)
+ };
}
+ var values = _.clone(this.get('value'));
+ values.push(result.id);
+ this.set({'value': values});
}
-
- this.set({'value': files});
this.render_value()
},
on_file_delete: function (event) {
event.stopPropagation();
var file_id=$(event.target).data("id");
if (file_id) {
- var files=[];
- for(var i in this.get('value')){
- if(file_id != this.get('value')[i].id){
- files.push(this.get('value')[i]);
- }
- else if(!this.get('value')[i].no_unlink) {
- this.ds_file.unlink([file_id]);
- }
+ var files = _.filter(this.get('value'), function (id) {return id != file_id;});
+ if(!this.data[file_id].no_unlink) {
+ this.ds_file.unlink([file_id]);
}
this.set({'value': files});
}
var self = this;
var content = QWeb.render("FieldStatus.content", {widget: self});
self.$el.html(content);
- var colors = JSON.parse((self.node.attrs || {}).statusbar_colors || "{}");
- var color = colors[self.get('value')];
- if (color) {
- self.$("oe_active").css("color", color);
- }
},
calc_domain: function() {
var d = instance.web.pyeval.eval('domain', this.build_domain());
'date' : 'instance.web.form.FieldDate',
'datetime' : 'instance.web.form.FieldDatetime',
'selection' : 'instance.web.form.FieldSelection',
+ 'radio' : 'instance.web.form.FieldRadio',
'many2one' : 'instance.web.form.FieldMany2One',
'many2onebutton' : 'instance.web.form.Many2OneButton',
'many2many' : 'instance.web.form.FieldMany2Many',