2012-11-29 11:32:58 +01:00
|
|
|
/* This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
|
|
|
this repository contains the full copyright notices and license terms. */
|
2013-01-04 21:29:48 +01:00
|
|
|
(function() {
|
|
|
|
|
'use strict';
|
2012-11-29 11:32:58 +01:00
|
|
|
|
2013-01-04 21:29:48 +01:00
|
|
|
Sao.View = Sao.class_(Object, {
|
|
|
|
|
init: function(screen, xml) {
|
|
|
|
|
this.screen = screen;
|
|
|
|
|
this.view_type = null;
|
|
|
|
|
this.el = null;
|
2013-03-04 19:08:16 +01:00
|
|
|
this.fields = {};
|
|
|
|
|
},
|
|
|
|
|
set_value: function() {
|
|
|
|
|
},
|
|
|
|
|
get_fields: function() {
|
|
|
|
|
return Object.keys(this.fields);
|
2013-01-04 21:29:48 +01:00
|
|
|
}
|
|
|
|
|
});
|
2012-11-29 11:32:58 +01:00
|
|
|
|
2013-01-04 21:29:48 +01:00
|
|
|
Sao.View.parse = function(screen, xml, children_field) {
|
|
|
|
|
switch (xml.children().prop('tagName')) {
|
|
|
|
|
case 'tree':
|
|
|
|
|
return new Sao.View.Tree(screen, xml, children_field);
|
|
|
|
|
case 'form':
|
2013-02-04 18:23:30 +01:00
|
|
|
return new Sao.View.Form(screen, xml);
|
2013-01-04 21:29:48 +01:00
|
|
|
}
|
|
|
|
|
};
|
2012-11-29 11:32:58 +01:00
|
|
|
|
2013-01-04 21:29:48 +01:00
|
|
|
Sao.View.tree_column_get = function(type) {
|
2013-01-22 17:13:26 +01:00
|
|
|
switch (type) {
|
|
|
|
|
case 'char':
|
|
|
|
|
return Sao.View.Tree.CharColumn;
|
|
|
|
|
case 'many2one':
|
|
|
|
|
return Sao.View.Tree.Many2OneColumn;
|
|
|
|
|
case 'date':
|
|
|
|
|
return Sao.View.Tree.DateColumn;
|
|
|
|
|
case 'one2many':
|
|
|
|
|
return Sao.View.Tree.One2ManyColumn;
|
|
|
|
|
case 'many2many':
|
|
|
|
|
return Sao.View.Tree.Many2ManyColumn;
|
|
|
|
|
case 'selection':
|
|
|
|
|
return Sao.View.Tree.SelectionColumn;
|
|
|
|
|
case 'float':
|
|
|
|
|
case 'numeric':
|
|
|
|
|
return Sao.View.Tree.FloatColumn;
|
|
|
|
|
case 'float_time':
|
|
|
|
|
return Sao.View.Tree.FloatTimeColumn;
|
|
|
|
|
case 'integer':
|
|
|
|
|
case 'biginteger':
|
|
|
|
|
return Sao.View.Tree.IntegerColumn;
|
2013-02-06 17:53:41 +01:00
|
|
|
case 'boolean':
|
|
|
|
|
return Sao.View.Tree.BooleanColumn;
|
2013-01-22 17:13:26 +01:00
|
|
|
default:
|
|
|
|
|
return Sao.View.Tree.CharColumn;
|
|
|
|
|
}
|
2013-01-04 21:29:48 +01:00
|
|
|
};
|
2012-11-29 23:57:26 +01:00
|
|
|
|
2013-01-04 21:29:48 +01:00
|
|
|
Sao.View.Tree = Sao.class_(Sao.View, {
|
|
|
|
|
init: function(screen, xml, children_field) {
|
|
|
|
|
Sao.View.Tree._super.init.call(this, screen, xml);
|
|
|
|
|
this.view_type = 'tree';
|
|
|
|
|
this.el = jQuery('<div/>', {
|
|
|
|
|
'class': 'treeview'
|
2012-11-29 23:57:26 +01:00
|
|
|
});
|
2013-01-04 21:29:48 +01:00
|
|
|
this.expanded = {};
|
|
|
|
|
this.children_field = children_field;
|
|
|
|
|
this.keyword_open = xml.children()[0].getAttribute('keyword_open');
|
2012-11-29 23:57:26 +01:00
|
|
|
|
2013-01-04 21:29:48 +01:00
|
|
|
// Columns
|
|
|
|
|
this.columns = [];
|
|
|
|
|
this.create_columns(screen.model, xml);
|
|
|
|
|
|
|
|
|
|
// Table of records
|
2013-04-18 13:07:21 +02:00
|
|
|
this.rows = [];
|
2013-01-04 21:29:48 +01:00
|
|
|
this.table = jQuery('<table/>', {
|
|
|
|
|
'class': 'tree'
|
|
|
|
|
});
|
|
|
|
|
this.el.append(this.table);
|
|
|
|
|
var thead = jQuery('<thead/>');
|
|
|
|
|
this.table.append(thead);
|
|
|
|
|
var tr = jQuery('<tr/>');
|
|
|
|
|
thead.append(tr);
|
|
|
|
|
this.columns.forEach(function(column) {
|
|
|
|
|
var th = jQuery('<th/>', {
|
|
|
|
|
'text': column.attributes.string
|
|
|
|
|
});
|
|
|
|
|
tr.append(th);
|
|
|
|
|
});
|
|
|
|
|
this.tbody = jQuery('<tbody/>');
|
|
|
|
|
this.table.append(this.tbody);
|
|
|
|
|
|
|
|
|
|
// Footer with pagination stuff
|
|
|
|
|
var footer = jQuery('<div/>', {
|
|
|
|
|
'class': 'treefooter'
|
|
|
|
|
});
|
|
|
|
|
this.previous_button = jQuery('<button/>').button({
|
|
|
|
|
'disabled': true,
|
|
|
|
|
'icons': {
|
|
|
|
|
primary: 'ui-icon-triangle-1-w'
|
|
|
|
|
},
|
|
|
|
|
'text': false,
|
|
|
|
|
'label': 'Previous' //TODO translation
|
|
|
|
|
});
|
|
|
|
|
footer.append(this.previous_button);
|
|
|
|
|
this.pagination = jQuery('<span/>', {
|
|
|
|
|
text: '0 / 0'
|
|
|
|
|
});
|
|
|
|
|
footer.append(this.pagination);
|
|
|
|
|
this.next_button = jQuery('<button/>').button({
|
|
|
|
|
'disabled': true,
|
|
|
|
|
'icons': {
|
|
|
|
|
primary: 'ui-icon-triangle-1-e'
|
|
|
|
|
},
|
|
|
|
|
'text': false,
|
|
|
|
|
'label': 'Next' //TODO translation
|
|
|
|
|
});
|
|
|
|
|
this.pagination.append(this.next_button);
|
|
|
|
|
this.el.append(footer);
|
|
|
|
|
},
|
|
|
|
|
create_columns: function(model, xml) {
|
|
|
|
|
xml.find('tree').children().each(function(pos, child) {
|
|
|
|
|
var attributes, column;
|
|
|
|
|
if (child.tagName == 'field') {
|
|
|
|
|
var name = child.getAttribute('name');
|
|
|
|
|
attributes = {
|
|
|
|
|
'name': child.getAttribute('name'),
|
|
|
|
|
'readonly': child.getAttribute('readonly') == 1,
|
|
|
|
|
'widget': child.getAttribute('widget'),
|
|
|
|
|
'tree_invisible': child.getAttribute(
|
|
|
|
|
'tree_invisible') == 1,
|
|
|
|
|
'expand': child.getAttribute('expand') == 1,
|
|
|
|
|
'icon': child.getAttribute('icon'),
|
|
|
|
|
'sum': child.getAttribute('sum'),
|
|
|
|
|
'width': child.getAttribute('width'),
|
|
|
|
|
'orientation': child.getAttribute('orientation'),
|
|
|
|
|
'float_time': child.getAttribute('float_time'),
|
|
|
|
|
'pre_validate': child.getAttribute('pre_validate') == 1,
|
|
|
|
|
'completion': child.getAttribute('completion') == 1
|
|
|
|
|
};
|
2013-01-22 17:13:26 +01:00
|
|
|
if (attributes.widget === null) {
|
|
|
|
|
attributes.widget = model.fields[name].description.type;
|
|
|
|
|
}
|
2013-01-04 21:29:48 +01:00
|
|
|
var attribute_names = ['relation', 'domain', 'selection',
|
|
|
|
|
'relation_field', 'string', 'views', 'invisible',
|
|
|
|
|
'add_remove', 'sort', 'context', 'filename'];
|
|
|
|
|
for (var i in attribute_names) {
|
|
|
|
|
var attr = attribute_names[i];
|
|
|
|
|
if ((attr in model.fields[name].description) &&
|
|
|
|
|
(child.getAttribute(attr) === null)) {
|
|
|
|
|
attributes[attr] = model.fields[name]
|
|
|
|
|
.description[attr];
|
|
|
|
|
}
|
2012-12-26 14:40:27 +01:00
|
|
|
}
|
2013-01-04 21:29:48 +01:00
|
|
|
var ColumnFactory = Sao.View.tree_column_get(
|
|
|
|
|
attributes.widget);
|
|
|
|
|
column = new ColumnFactory(model, attributes);
|
2013-03-04 19:08:16 +01:00
|
|
|
this.fields[name] = true;
|
2013-01-04 21:29:48 +01:00
|
|
|
} else if (child.tagName == 'button') {
|
|
|
|
|
attributes = {
|
|
|
|
|
'help': child.getAttribute('help'),
|
|
|
|
|
'string': child.getAttribute('string'),
|
|
|
|
|
'confirm': child.getAttribute('confirm'),
|
2013-05-06 15:03:25 +02:00
|
|
|
'name': child.getAttribute('name'),
|
|
|
|
|
'states': child.getAttribute('states')
|
2013-01-04 21:29:48 +01:00
|
|
|
};
|
2013-05-02 17:23:37 +02:00
|
|
|
column = new Sao.View.Tree.ButtonColumn(this.screen,
|
|
|
|
|
attributes);
|
2012-12-26 14:40:27 +01:00
|
|
|
}
|
2013-03-04 19:08:16 +01:00
|
|
|
this.columns.push(column);
|
|
|
|
|
}.bind(this));
|
2013-01-04 21:29:48 +01:00
|
|
|
},
|
|
|
|
|
display: function() {
|
2013-04-18 13:07:21 +02:00
|
|
|
this.rows = [];
|
2013-01-04 21:29:48 +01:00
|
|
|
this.tbody.empty();
|
|
|
|
|
var add_row = function(record, pos, group) {
|
|
|
|
|
var tree_row = new Sao.View.Tree.Row(this, record, pos);
|
2013-04-18 13:07:21 +02:00
|
|
|
this.rows.push(tree_row);
|
2013-01-04 21:29:48 +01:00
|
|
|
tree_row.display();
|
2012-12-01 23:45:03 +01:00
|
|
|
};
|
2013-01-04 21:29:48 +01:00
|
|
|
this.screen.group.forEach(add_row.bind(this));
|
|
|
|
|
},
|
|
|
|
|
switch_: function(path) {
|
|
|
|
|
this.screen.row_activate();
|
|
|
|
|
},
|
|
|
|
|
select_changed: function(record) {
|
|
|
|
|
this.screen.current_record = record;
|
|
|
|
|
// TODO validate if editable
|
|
|
|
|
// TODO update_children
|
2013-03-22 16:56:41 +01:00
|
|
|
},
|
|
|
|
|
selected_records: function() {
|
|
|
|
|
var records = [];
|
2013-04-18 13:07:21 +02:00
|
|
|
this.rows.forEach(function(row) {
|
|
|
|
|
if (row.is_selected()) {
|
|
|
|
|
records.push(row.record);
|
2013-03-22 16:56:41 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return records;
|
2012-12-01 23:45:03 +01:00
|
|
|
}
|
2013-01-04 21:29:48 +01:00
|
|
|
});
|
2012-11-29 23:57:26 +01:00
|
|
|
|
2013-01-04 21:29:48 +01:00
|
|
|
Sao.View.Tree.Row = Sao.class_(Object, {
|
|
|
|
|
init: function(tree, record, pos, parent) {
|
|
|
|
|
this.tree = tree;
|
|
|
|
|
this.record = record;
|
|
|
|
|
this.children_field = tree.children_field;
|
|
|
|
|
this.expander = null;
|
|
|
|
|
this.expander_icon = null;
|
|
|
|
|
var path = [];
|
|
|
|
|
if (parent) {
|
|
|
|
|
path = jQuery.extend([], parent.path.split('.'));
|
|
|
|
|
}
|
|
|
|
|
path.push(pos);
|
|
|
|
|
this.path = path.join('.');
|
|
|
|
|
this.el = jQuery('<tr/>');
|
|
|
|
|
this.el.click(this.select_row.bind(this));
|
|
|
|
|
var switch_ = function() {
|
|
|
|
|
this.el.addClass('ui-state-highlight');
|
|
|
|
|
this.tree.select_changed(this.record);
|
|
|
|
|
this.tree.switch_(path);
|
|
|
|
|
};
|
|
|
|
|
this.el.dblclick(switch_.bind(this));
|
|
|
|
|
},
|
|
|
|
|
is_expanded: function() {
|
|
|
|
|
return (this.path in this.tree.expanded);
|
|
|
|
|
},
|
|
|
|
|
display: function() {
|
|
|
|
|
var depth = this.path.split('.').length;
|
|
|
|
|
var update_expander = function() {
|
|
|
|
|
if (jQuery.isEmptyObject(
|
|
|
|
|
this.record.field_get(
|
|
|
|
|
this.children_field))) {
|
2012-11-29 23:57:26 +01:00
|
|
|
|
2013-01-04 21:29:48 +01:00
|
|
|
this.expander_icon.hide();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
for (var i = 0; i < this.tree.columns.length; i++) {
|
|
|
|
|
var td = jQuery('<td/>');
|
|
|
|
|
if ((i === 0) && this.children_field) {
|
|
|
|
|
var expanded = 'ui-icon-plus';
|
|
|
|
|
if (this.is_expanded()) {
|
|
|
|
|
expanded = 'ui-icon-minus';
|
|
|
|
|
}
|
|
|
|
|
this.expander = jQuery('<span/>', {
|
|
|
|
|
'class': 'expander'
|
|
|
|
|
});
|
|
|
|
|
this.expander.html(' ');
|
|
|
|
|
// 16 == minimum width of icon
|
|
|
|
|
this.expander.css('width', ((depth * 10) + 16) + 'px');
|
|
|
|
|
this.expander.css('float', 'left');
|
|
|
|
|
this.expander.click(this.toggle_row.bind(this));
|
|
|
|
|
this.expander_icon = jQuery('<i/>', {
|
|
|
|
|
'class': 'ui-icon ' + expanded
|
|
|
|
|
});
|
|
|
|
|
this.expander.append(this.expander_icon);
|
|
|
|
|
this.expander_icon.css('float', 'right');
|
|
|
|
|
td.append(this.expander);
|
|
|
|
|
this.record.load(this.children_field).done(
|
|
|
|
|
update_expander.bind(this));
|
|
|
|
|
}
|
|
|
|
|
var column = this.tree.columns[i];
|
|
|
|
|
td.append(column.render(this.record));
|
|
|
|
|
this.el.append(td);
|
|
|
|
|
}
|
|
|
|
|
this.tree.tbody.append(this.el);
|
|
|
|
|
if (this.is_expanded()) {
|
|
|
|
|
var add_children = function() {
|
|
|
|
|
var add_row = function(record, pos, group) {
|
|
|
|
|
var tree_row = new Sao.View.Tree.Row(this.tree, record,
|
|
|
|
|
pos, this);
|
|
|
|
|
tree_row.display();
|
|
|
|
|
};
|
|
|
|
|
var children = this.record.field_get_client(children_field);
|
|
|
|
|
children.forEach(add_row.bind(this));
|
|
|
|
|
};
|
|
|
|
|
var children_field = this.children_field;
|
|
|
|
|
this.record.load(this.children_field).done(
|
|
|
|
|
add_children.bind(this));
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
toggle_row: function() {
|
|
|
|
|
if (this.is_expanded()) {
|
|
|
|
|
this.expander_icon.removeClass('ui-icon-minus');
|
|
|
|
|
this.expander_icon.addClass('ui-icon-plus');
|
|
|
|
|
delete this.tree.expanded[this.path];
|
|
|
|
|
} else {
|
|
|
|
|
this.expander_icon.removeClass('ui-icon-plus');
|
|
|
|
|
this.expander_icon.addClass('ui-icon-minus');
|
|
|
|
|
this.tree.expanded[this.path] = this;
|
|
|
|
|
}
|
|
|
|
|
this.tree.display();
|
|
|
|
|
},
|
|
|
|
|
select_row: function() {
|
|
|
|
|
this.el.toggleClass('ui-state-highlight');
|
2013-03-22 16:56:41 +01:00
|
|
|
if (this.is_selected()) {
|
2013-01-04 21:29:48 +01:00
|
|
|
this.tree.select_changed(this.record);
|
|
|
|
|
} else {
|
|
|
|
|
this.tree.select_changed(null);
|
|
|
|
|
}
|
2013-03-22 16:56:41 +01:00
|
|
|
},
|
|
|
|
|
is_selected: function() {
|
|
|
|
|
return this.el.hasClass('ui-state-highlight');
|
2013-01-04 21:29:48 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.CharColumn = Sao.class_(Object, {
|
|
|
|
|
init: function(model, attributes) {
|
|
|
|
|
this.type = 'field';
|
2013-02-06 17:34:32 +01:00
|
|
|
this.model = model;
|
2013-01-04 21:29:48 +01:00
|
|
|
this.field = model.fields[attributes.name];
|
|
|
|
|
this.attributes = attributes;
|
|
|
|
|
},
|
2013-01-22 17:13:26 +01:00
|
|
|
get_cell: function() {
|
|
|
|
|
var cell = jQuery('<div/>');
|
|
|
|
|
cell.css('text-overflow', 'ellipsis');
|
|
|
|
|
cell.css('overflow', 'hidden');
|
|
|
|
|
cell.css('white-space', 'nowrap');
|
|
|
|
|
cell.addClass('column-char');
|
2013-01-04 21:29:48 +01:00
|
|
|
return cell;
|
2013-01-22 17:13:26 +01:00
|
|
|
},
|
|
|
|
|
update_text: function(cell, record) {
|
|
|
|
|
cell.text(this.field.get_client(record));
|
|
|
|
|
},
|
|
|
|
|
render: function(record) {
|
|
|
|
|
var cell = this.get_cell();
|
2013-02-04 18:29:15 +01:00
|
|
|
record.load(this.attributes.name).done(function() {
|
2013-01-22 17:13:26 +01:00
|
|
|
this.update_text(cell, record);
|
|
|
|
|
}.bind(this));
|
|
|
|
|
return cell;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.IntegerColumn = Sao.class_(Sao.View.Tree.CharColumn, {
|
|
|
|
|
get_cell: function() {
|
|
|
|
|
var cell = Sao.View.Tree.IntegerColumn._super.get_cell.call(this);
|
|
|
|
|
cell.css('text-align', 'right');
|
|
|
|
|
cell.removeClass('column-char');
|
|
|
|
|
cell.addClass('column-integer');
|
|
|
|
|
return cell;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.FloatColumn = Sao.class_(Sao.View.Tree.IntegerColumn, {
|
|
|
|
|
init: function(model, attributes) {
|
|
|
|
|
Sao.View.Tree.FloatColumn._super.init.call(this, model, attributes);
|
|
|
|
|
},
|
|
|
|
|
get_cell: function() {
|
|
|
|
|
var cell = Sao.View.Tree.FloatColumn._super.get_cell.call(this);
|
|
|
|
|
cell.removeClass('column-integer');
|
|
|
|
|
cell.addClass('column-float');
|
|
|
|
|
return cell;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-02-06 17:53:41 +01:00
|
|
|
Sao.View.Tree.BooleanColumn = Sao.class_(Sao.View.Tree.IntegerColumn, {
|
|
|
|
|
get_cell: function() {
|
|
|
|
|
return jQuery('<input/>', {
|
|
|
|
|
'type': 'checkbox',
|
|
|
|
|
'disabled': true,
|
|
|
|
|
'class': 'column-boolean'
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
update_text: function(cell, record) {
|
|
|
|
|
cell.prop('checked', this.field.get(record));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-01-22 17:13:26 +01:00
|
|
|
Sao.View.Tree.Many2OneColumn = Sao.class_(Sao.View.Tree.CharColumn, {
|
|
|
|
|
get_cell: function() {
|
|
|
|
|
var cell = Sao.View.Tree.Many2OneColumn._super.get_cell.call(this);
|
|
|
|
|
cell.removeClass('column-char');
|
|
|
|
|
cell.addClass('column-many2one');
|
|
|
|
|
return cell;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.SelectionColumn = Sao.class_(Sao.View.Tree.CharColumn, {
|
|
|
|
|
init: function(model, attributes) {
|
2013-02-04 18:29:15 +01:00
|
|
|
Sao.View.Tree.SelectionColumn._super.init.call(this, model,
|
|
|
|
|
attributes);
|
2013-02-06 17:34:32 +01:00
|
|
|
Sao.common.selection_mixin.init.call(this);
|
|
|
|
|
this.init_selection();
|
|
|
|
|
},
|
|
|
|
|
init_selection: function(key) {
|
|
|
|
|
Sao.common.selection_mixin.init_selection.call(this, key);
|
|
|
|
|
},
|
|
|
|
|
update_selection: function(record, callback) {
|
|
|
|
|
Sao.common.selection_mixin.update_selection.call(this, record,
|
|
|
|
|
this.field, callback);
|
2013-01-22 17:13:26 +01:00
|
|
|
},
|
|
|
|
|
get_cell: function() {
|
|
|
|
|
var cell = Sao.View.Tree.Many2OneColumn._super.get_cell.call(this);
|
|
|
|
|
cell.removeClass('column-char');
|
|
|
|
|
cell.addClass('column-selection');
|
|
|
|
|
return cell;
|
|
|
|
|
},
|
|
|
|
|
update_text: function(cell, record) {
|
2013-02-06 17:34:32 +01:00
|
|
|
this.update_selection(record, function() {
|
|
|
|
|
var value = this.field.get(record);
|
2013-05-02 17:52:19 +02:00
|
|
|
this.selection.forEach(function(e) {
|
|
|
|
|
if (e[0] == value) {
|
|
|
|
|
cell.text(e[1]);
|
|
|
|
|
}
|
|
|
|
|
});
|
2013-02-06 17:34:32 +01:00
|
|
|
}.bind(this));
|
2013-01-22 17:13:26 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.DateColumn = Sao.class_(Sao.View.Tree.CharColumn, {
|
|
|
|
|
init: function(model, attributes) {
|
|
|
|
|
Sao.View.Tree.DateColumn._super.init.call(this, model, attributes);
|
|
|
|
|
this.date_format = Sao.common.date_format();
|
|
|
|
|
},
|
|
|
|
|
update_text: function(cell, record) {
|
|
|
|
|
var text;
|
|
|
|
|
var value = this.field.get_client(record);
|
2013-02-04 18:29:15 +01:00
|
|
|
var pad = function(txt) {
|
2013-01-22 17:13:26 +01:00
|
|
|
return (txt.toString().length < 2) ? '0' + txt : txt;
|
|
|
|
|
};
|
|
|
|
|
if (value) {
|
|
|
|
|
text = this.date_format.replace('%d', pad(value.getDate()));
|
|
|
|
|
text = text.replace('%m', pad(value.getMonth() + 1));
|
|
|
|
|
text = text.replace('%Y', value.getFullYear());
|
|
|
|
|
text = text.replace('%y', value.getFullYear().toString()
|
|
|
|
|
.substring(2, 4));
|
|
|
|
|
} else {
|
|
|
|
|
text = '';
|
|
|
|
|
}
|
|
|
|
|
cell.text(text);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.One2ManyColumn = Sao.class_(Sao.View.Tree.CharColumn, {
|
|
|
|
|
update_text: function(cell, record) {
|
|
|
|
|
cell.text('( ' + this.field.get_client(record).length + ' )');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.Many2ManyColumn = Sao.class_(Sao.View.Tree.One2ManyColumn, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.FloatTimeColumn = Sao.class_(Sao.View.Tree.CharColumn, {
|
|
|
|
|
init: function(model, attributes) {
|
2013-02-06 17:34:32 +01:00
|
|
|
Sao.View.Tree.FloatTimeColumn._super.init.call(this, model,
|
2013-02-04 18:29:15 +01:00
|
|
|
attributes);
|
2013-02-06 17:34:32 +01:00
|
|
|
this.conv = null; // TODO
|
2013-01-22 17:13:26 +01:00
|
|
|
},
|
|
|
|
|
update_text: function(cell, record) {
|
2013-02-04 18:29:15 +01:00
|
|
|
cell.text(Sao.common.text_to_float_time(
|
|
|
|
|
this.field.get_client(record), this.conv));
|
2013-01-04 21:29:48 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Tree.ButtonColumn = Sao.class_(Object, {
|
2013-05-02 17:23:37 +02:00
|
|
|
init: function(screen, attributes) {
|
|
|
|
|
this.screen = screen;
|
2013-01-04 21:29:48 +01:00
|
|
|
this.type = 'button';
|
|
|
|
|
this.attributes = attributes;
|
|
|
|
|
},
|
2013-05-02 17:23:37 +02:00
|
|
|
render: function(record) {
|
|
|
|
|
var button = new Sao.common.Button(this.attributes);
|
|
|
|
|
button.el.click(record, this.button_clicked.bind(this));
|
2013-05-06 15:03:25 +02:00
|
|
|
var fields = jQuery.map(this.screen.model.fields,
|
|
|
|
|
function(field, name) {
|
|
|
|
|
if ((field.description.loading || 'eager') ==
|
|
|
|
|
'eager') {
|
|
|
|
|
return name;
|
|
|
|
|
} else {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// Wait at least one eager field is loaded before evaluating states
|
|
|
|
|
record.load(fields[0]).done(function() {
|
|
|
|
|
button.set_state(record);
|
|
|
|
|
});
|
2013-05-02 17:23:37 +02:00
|
|
|
return button.el;
|
|
|
|
|
},
|
|
|
|
|
button_clicked: function(event) {
|
|
|
|
|
var record = event.data;
|
2013-05-02 17:59:33 +02:00
|
|
|
if (record != this.screen.current_record) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-05-02 17:23:37 +02:00
|
|
|
// TODO check state
|
|
|
|
|
this.screen.button(this.attributes);
|
2013-01-04 21:29:48 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-02-04 18:23:30 +01:00
|
|
|
Sao.View.Form = Sao.class_(Sao.View, {
|
|
|
|
|
init: function(screen, xml) {
|
|
|
|
|
Sao.View.Form._super.init.call(this, screen, xml);
|
|
|
|
|
this.view_type = 'form';
|
|
|
|
|
this.el = jQuery('<div/>', {
|
|
|
|
|
'class': 'form'
|
|
|
|
|
});
|
|
|
|
|
this.widgets = {};
|
|
|
|
|
this.widget_id = 0;
|
|
|
|
|
this.state_widgets = [];
|
2013-02-05 12:39:19 +01:00
|
|
|
var root = xml.children()[0];
|
|
|
|
|
var container = this.parse(screen.model, root);
|
2013-02-04 18:23:30 +01:00
|
|
|
this.el.append(container.el);
|
|
|
|
|
},
|
2013-02-05 12:39:19 +01:00
|
|
|
parse: function(model, node, container) {
|
|
|
|
|
if (container === undefined) {
|
|
|
|
|
container = new Sao.View.Form.Container(
|
2013-02-05 15:50:56 +01:00
|
|
|
Number(node.getAttribute('col') || 4));
|
2013-02-05 12:39:19 +01:00
|
|
|
}
|
2013-02-04 18:23:30 +01:00
|
|
|
var _parse = function(index, child) {
|
2013-02-05 12:39:19 +01:00
|
|
|
var attributes = {
|
|
|
|
|
'name': child.getAttribute('name'),
|
2013-02-05 13:00:24 +01:00
|
|
|
'widget': child.getAttribute('widget'),
|
2013-05-06 15:03:25 +02:00
|
|
|
'string': child.getAttribute('string'),
|
|
|
|
|
'states': child.getAttribute('states')
|
2013-02-05 12:39:19 +01:00
|
|
|
};
|
2013-05-06 15:03:25 +02:00
|
|
|
['readonly', 'invisible'].forEach(function(name) {
|
|
|
|
|
if (child.getAttribute(name)) {
|
|
|
|
|
attributes[name] = child.getAttribute(name) == 1;
|
|
|
|
|
}
|
|
|
|
|
});
|
2013-02-04 18:23:30 +01:00
|
|
|
switch (child.tagName) {
|
|
|
|
|
case 'image':
|
|
|
|
|
// TODO
|
|
|
|
|
break;
|
|
|
|
|
case 'separator':
|
2013-02-05 15:52:13 +01:00
|
|
|
this._parse_separator(
|
|
|
|
|
model, child, container, attributes);
|
2013-02-04 18:23:30 +01:00
|
|
|
break;
|
|
|
|
|
case 'label':
|
2013-02-05 13:00:24 +01:00
|
|
|
this._parse_label(model, child, container, attributes);
|
2013-02-04 18:23:30 +01:00
|
|
|
break;
|
|
|
|
|
case 'newline':
|
|
|
|
|
container.add_row();
|
|
|
|
|
break;
|
|
|
|
|
case 'button':
|
2013-05-02 17:23:37 +02:00
|
|
|
this._parse_button(child, container, attributes);
|
2013-02-04 18:23:30 +01:00
|
|
|
break;
|
|
|
|
|
case 'notebook':
|
2013-02-05 13:00:24 +01:00
|
|
|
this._parse_notebook(
|
|
|
|
|
model, child, container, attributes);
|
2013-02-04 18:23:30 +01:00
|
|
|
break;
|
|
|
|
|
case 'page':
|
2013-02-05 13:00:24 +01:00
|
|
|
this._parse_page(model, child, container, attributes);
|
2013-02-04 18:23:30 +01:00
|
|
|
break;
|
|
|
|
|
case 'field':
|
2013-02-05 13:00:24 +01:00
|
|
|
this._parse_field(model, child, container, attributes);
|
2013-02-04 18:23:30 +01:00
|
|
|
break;
|
|
|
|
|
case 'group':
|
2013-02-05 15:52:31 +01:00
|
|
|
this._parse_group(model, child, container, attributes);
|
2013-02-04 18:23:30 +01:00
|
|
|
break;
|
|
|
|
|
case 'hpaned':
|
|
|
|
|
// TODO
|
|
|
|
|
break;
|
|
|
|
|
case 'vpaned':
|
|
|
|
|
// TODO
|
|
|
|
|
break;
|
|
|
|
|
case 'child':
|
|
|
|
|
// TODO
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
};
|
2013-02-22 16:31:32 +01:00
|
|
|
jQuery(node).children().each(_parse.bind(this));
|
2013-02-04 18:23:30 +01:00
|
|
|
return container;
|
|
|
|
|
},
|
2013-02-05 15:52:13 +01:00
|
|
|
_parse_separator: function(model, node, container, attributes) {
|
|
|
|
|
var name = attributes.name;
|
|
|
|
|
var text = attributes.string;
|
|
|
|
|
if (name in model.fields) {
|
2013-05-06 15:03:25 +02:00
|
|
|
if (!attributes.states && (name in model.fields)) {
|
|
|
|
|
attributes.states = model.fields[name].description.states;
|
|
|
|
|
}
|
2013-02-05 15:52:13 +01:00
|
|
|
if (!text) {
|
|
|
|
|
text = model.fields[name].description.string;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var separator = new Sao.View.Form.Separator(text, attributes);
|
2013-05-06 15:03:25 +02:00
|
|
|
this.state_widgets.push(separator);
|
2013-02-05 15:52:13 +01:00
|
|
|
container.add(
|
|
|
|
|
Number(node.getAttribute('colspan') || 1),
|
|
|
|
|
separator);
|
|
|
|
|
},
|
2013-02-05 13:00:24 +01:00
|
|
|
_parse_label: function(model, node, container, attributes) {
|
|
|
|
|
var name = attributes.name;
|
|
|
|
|
var text = attributes.string;
|
|
|
|
|
if (name in model.fields) {
|
|
|
|
|
// TODO exclude field
|
2013-05-06 15:03:25 +02:00
|
|
|
if (!attributes.states && (name in model.fields)) {
|
|
|
|
|
attributes.states = model.fields[name].description.states;
|
|
|
|
|
}
|
2013-02-05 13:00:24 +01:00
|
|
|
if (!text) {
|
|
|
|
|
// TODO RTL and translation
|
|
|
|
|
text = model.fields[name]
|
|
|
|
|
.description.string + ':';
|
|
|
|
|
}
|
|
|
|
|
if (node.getAttribute('xalign') === undefined) {
|
|
|
|
|
node.setAttribute('xalign', 1.0);
|
|
|
|
|
}
|
|
|
|
|
} else if (!text) {
|
|
|
|
|
// TODO get content
|
|
|
|
|
}
|
|
|
|
|
var label;
|
|
|
|
|
if (text) {
|
|
|
|
|
label = new Sao.View.Form.Label(text, attributes);
|
|
|
|
|
this.state_widgets.push(label);
|
|
|
|
|
}
|
|
|
|
|
container.add(
|
|
|
|
|
Number(node.getAttribute('colspan') || 1),
|
|
|
|
|
label);
|
|
|
|
|
// TODO help
|
|
|
|
|
},
|
2013-05-02 17:23:37 +02:00
|
|
|
_parse_button: function(node, container, attributes) {
|
|
|
|
|
var button = new Sao.common.Button(attributes);
|
|
|
|
|
this.state_widgets.push(button);
|
|
|
|
|
container.add(
|
|
|
|
|
Number(node.getAttribute('colspan') || 1),
|
|
|
|
|
button);
|
|
|
|
|
button.el.click(button, this.button_clicked.bind(this));
|
|
|
|
|
// TODO help
|
|
|
|
|
},
|
2013-02-05 13:00:24 +01:00
|
|
|
_parse_notebook: function(model, node, container, attributes) {
|
|
|
|
|
var notebook = new Sao.View.Form.Notebook(attributes);
|
|
|
|
|
this.state_widgets.push(notebook);
|
|
|
|
|
container.add(
|
|
|
|
|
Number(node.getAttribute('colspan') || 1),
|
|
|
|
|
notebook);
|
|
|
|
|
this.parse(model, node, notebook);
|
|
|
|
|
},
|
|
|
|
|
_parse_page: function(model, node, container, attributes) {
|
|
|
|
|
var text = attributes.string;
|
|
|
|
|
if (attributes.name in model.fields) {
|
|
|
|
|
// TODO check exclude
|
|
|
|
|
// sync attributes
|
|
|
|
|
if (!text) {
|
|
|
|
|
text = model.fields[attributes.name]
|
|
|
|
|
.description.string;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!text) {
|
|
|
|
|
text = 'No String Attr.'; // TODO translate
|
|
|
|
|
}
|
|
|
|
|
var page = this.parse(model, node);
|
2013-05-06 15:03:25 +02:00
|
|
|
page = new Sao.View.Form.Page(container.add(page.el, text),
|
|
|
|
|
attributes);
|
|
|
|
|
this.state_widgets.push(page);
|
2013-02-05 13:00:24 +01:00
|
|
|
},
|
|
|
|
|
_parse_field: function(model, node, container, attributes) {
|
|
|
|
|
var name = attributes.name;
|
|
|
|
|
// TODO exclude field
|
|
|
|
|
if (!(name in model.fields)) {
|
|
|
|
|
container.add(
|
|
|
|
|
Number(node.getAttribute('colspan') || 1));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (attributes.widget === null) {
|
|
|
|
|
attributes.widget = model.fields[name]
|
|
|
|
|
.description.type;
|
|
|
|
|
}
|
2013-05-06 15:03:25 +02:00
|
|
|
var attribute_names = ['relation', 'domain', 'selection',
|
|
|
|
|
'relation_field', 'string', 'views', 'add_remove', 'sort',
|
|
|
|
|
'context', 'size', 'filename', 'autocomplete', 'translate',
|
2013-02-05 13:00:24 +01:00
|
|
|
'create', 'delete'];
|
|
|
|
|
for (var i in attribute_names) {
|
|
|
|
|
var attr = attribute_names[i];
|
|
|
|
|
if ((attr in model.fields[name].description) &&
|
|
|
|
|
(node.getAttribute(attr) === null)) {
|
|
|
|
|
attributes[attr] = model.fields[name]
|
|
|
|
|
.description[attr];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var WidgetFactory = Sao.View.form_widget_get(
|
|
|
|
|
attributes.widget);
|
|
|
|
|
if (!WidgetFactory) {
|
|
|
|
|
container.add(
|
|
|
|
|
Number(node.getAttribute('colspan') || 1));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var widget = new WidgetFactory(name, model, attributes);
|
|
|
|
|
widget.position = this.widget_id += 1;
|
2013-02-21 14:16:19 +01:00
|
|
|
widget.view = this;
|
2013-02-05 13:00:24 +01:00
|
|
|
// TODO expand, fill, help, height, width
|
|
|
|
|
container.add(
|
|
|
|
|
Number(node.getAttribute('colspan') || 1),
|
|
|
|
|
widget);
|
|
|
|
|
if (this.widgets[name] === undefined) {
|
|
|
|
|
this.widgets[name] = [];
|
|
|
|
|
}
|
|
|
|
|
this.widgets[name].push(widget);
|
2013-03-04 19:08:16 +01:00
|
|
|
this.fields[name] = true;
|
2013-02-05 13:00:24 +01:00
|
|
|
},
|
2013-02-05 15:52:31 +01:00
|
|
|
_parse_group: function(model, node, container, attributes) {
|
|
|
|
|
var group = new Sao.View.Form.Group(attributes);
|
|
|
|
|
group.add(this.parse(model, node));
|
|
|
|
|
this.state_widgets.push(group);
|
|
|
|
|
container.add(
|
|
|
|
|
Number(node.getAttribute('colspan') || 1),
|
|
|
|
|
group);
|
|
|
|
|
},
|
2013-02-04 18:23:30 +01:00
|
|
|
display: function() {
|
|
|
|
|
var record = this.screen.current_record;
|
2013-02-06 17:34:32 +01:00
|
|
|
var field;
|
|
|
|
|
var name;
|
|
|
|
|
var promesses = {};
|
|
|
|
|
if (record) {
|
|
|
|
|
// Force to set fields in record
|
|
|
|
|
// Get first the lazy one to reduce number of requests
|
|
|
|
|
var fields = [];
|
|
|
|
|
for (name in record.model.fields) {
|
|
|
|
|
field = record.model.fields[name];
|
|
|
|
|
fields.push([name, field.description.loading || 'eager']);
|
|
|
|
|
}
|
|
|
|
|
fields.sort(function(a, b) {
|
|
|
|
|
return a[1].localeCompare(b[1]);
|
|
|
|
|
});
|
|
|
|
|
fields.forEach(function(e) {
|
|
|
|
|
var name = e[0];
|
|
|
|
|
promesses[name] = record.load(name);
|
|
|
|
|
});
|
|
|
|
|
}
|
2013-05-06 15:03:25 +02:00
|
|
|
var set_state = function(record, field, name) {
|
|
|
|
|
var prm = jQuery.when();
|
|
|
|
|
if (name in promesses) {
|
|
|
|
|
prm = promesses[name];
|
|
|
|
|
}
|
|
|
|
|
prm.done(function() {
|
|
|
|
|
field.set_state(record);
|
|
|
|
|
});
|
|
|
|
|
};
|
2013-02-06 17:34:32 +01:00
|
|
|
var display = function(record, field, name) {
|
|
|
|
|
return function(widget) {
|
|
|
|
|
var prm = jQuery.when();
|
|
|
|
|
if (name in promesses) {
|
|
|
|
|
prm = promesses[name];
|
|
|
|
|
}
|
|
|
|
|
prm.done(function() {
|
|
|
|
|
widget.display(record, field);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
for (name in this.widgets) {
|
2013-02-04 18:23:30 +01:00
|
|
|
var widgets = this.widgets[name];
|
2013-02-06 17:34:32 +01:00
|
|
|
field = null;
|
2013-02-04 18:23:30 +01:00
|
|
|
if (record) {
|
|
|
|
|
field = record.model.fields[name];
|
|
|
|
|
}
|
2013-05-06 15:03:25 +02:00
|
|
|
if (field) {
|
|
|
|
|
set_state(record, field, name);
|
|
|
|
|
}
|
2013-02-06 17:34:32 +01:00
|
|
|
widgets.forEach(display(record, field, name));
|
2013-02-04 18:23:30 +01:00
|
|
|
}
|
2013-05-06 15:03:25 +02:00
|
|
|
jQuery.when.apply(jQuery,
|
|
|
|
|
jQuery.map(promesses, function(p) {
|
|
|
|
|
return p;
|
|
|
|
|
})
|
|
|
|
|
).done(function() {
|
|
|
|
|
for (var j in this.state_widgets) {
|
|
|
|
|
var state_widget = this.state_widgets[j];
|
|
|
|
|
state_widget.set_state(record);
|
|
|
|
|
}
|
|
|
|
|
}.bind(this));
|
2013-03-04 19:08:16 +01:00
|
|
|
},
|
|
|
|
|
set_value: function() {
|
|
|
|
|
var record = this.screen.current_record;
|
|
|
|
|
if (record) {
|
|
|
|
|
var set_value = function(widget) {
|
|
|
|
|
widget.set_value(record, this);
|
|
|
|
|
};
|
|
|
|
|
for (var name in this.widgets) {
|
|
|
|
|
if (name in record.model.fields) {
|
|
|
|
|
var widgets = this.widgets[name];
|
|
|
|
|
var field = record.model.fields[name];
|
|
|
|
|
widgets.forEach(set_value, field);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-05-02 17:23:37 +02:00
|
|
|
},
|
|
|
|
|
button_clicked: function(event) {
|
|
|
|
|
var button = event.data;
|
|
|
|
|
var record = this.screen.current_record;
|
|
|
|
|
var fields = Object.keys(this.fields);
|
|
|
|
|
if (!record.validate(fields)) {
|
|
|
|
|
this.screen.display();
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
this.screen.button(button.attributes);
|
|
|
|
|
}
|
2013-02-04 18:23:30 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Container = Sao.class_(Object, {
|
|
|
|
|
init: function(col) {
|
|
|
|
|
if (col === undefined) col = 4;
|
|
|
|
|
this.col = col;
|
|
|
|
|
this.el = jQuery('<table/>');
|
|
|
|
|
this.add_row();
|
|
|
|
|
},
|
|
|
|
|
add_row: function() {
|
2013-02-05 12:39:19 +01:00
|
|
|
this.el.append(jQuery('<tr/>'));
|
|
|
|
|
},
|
|
|
|
|
row: function() {
|
|
|
|
|
return this.el.children().children('tr').last();
|
2013-02-04 18:23:30 +01:00
|
|
|
},
|
|
|
|
|
add: function(colspan, widget) {
|
|
|
|
|
if (colspan === undefined) colspan = 1;
|
2013-02-05 15:51:38 +01:00
|
|
|
var len = 0;
|
2013-02-05 12:39:19 +01:00
|
|
|
var row = this.row();
|
2013-02-05 15:51:38 +01:00
|
|
|
row.children().map(function(i, e) {
|
|
|
|
|
len += Number(jQuery(e).attr('colspan') || 1);
|
|
|
|
|
});
|
2013-02-05 12:39:19 +01:00
|
|
|
if (len + colspan > this.col) {
|
2013-02-04 18:23:30 +01:00
|
|
|
this.add_row();
|
2013-02-05 12:39:19 +01:00
|
|
|
row = this.row();
|
2013-02-04 18:23:30 +01:00
|
|
|
}
|
|
|
|
|
var el;
|
|
|
|
|
if (widget) {
|
|
|
|
|
el = widget.el;
|
|
|
|
|
}
|
2013-02-05 12:39:19 +01:00
|
|
|
var cell = row.append(jQuery('<td/>', {
|
2013-02-05 15:51:38 +01:00
|
|
|
'colspan': colspan
|
2013-02-04 18:23:30 +01:00
|
|
|
}).append(el));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var StateWidget = Sao.class_(Object, {
|
|
|
|
|
init: function(attributes) {
|
|
|
|
|
this.attributes = attributes;
|
|
|
|
|
},
|
2013-05-06 15:03:25 +02:00
|
|
|
set_state: function(record) {
|
|
|
|
|
var state_changes;
|
|
|
|
|
if (record) {
|
|
|
|
|
state_changes = record.expr_eval(this.attributes.states || {});
|
|
|
|
|
} else {
|
|
|
|
|
state_changes = {};
|
|
|
|
|
}
|
|
|
|
|
var invisible = state_changes.invisible;
|
|
|
|
|
if (invisible === undefined) {
|
|
|
|
|
invisible = this.attributes.invisible;
|
|
|
|
|
}
|
|
|
|
|
if (invisible) {
|
|
|
|
|
this.hide();
|
|
|
|
|
} else {
|
|
|
|
|
this.show();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
show: function() {
|
|
|
|
|
this.el.show();
|
|
|
|
|
},
|
|
|
|
|
hide: function() {
|
|
|
|
|
this.el.hide();
|
2013-02-04 18:23:30 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-02-05 15:52:13 +01:00
|
|
|
Sao.View.Form.Separator = Sao.class_(StateWidget, {
|
|
|
|
|
init: function(text, attributes) {
|
|
|
|
|
Sao.View.Form.Separator._super.init.call(this, attributes);
|
|
|
|
|
this.el = jQuery('<div/>', {
|
|
|
|
|
'class': 'form-separator'
|
|
|
|
|
});
|
|
|
|
|
if (text) {
|
|
|
|
|
this.el.append(jQuery('<p/>', {
|
|
|
|
|
'text': text
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
this.el.append(jQuery('<hr/>'));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-02-04 18:23:30 +01:00
|
|
|
Sao.View.Form.Label = Sao.class_(StateWidget, {
|
|
|
|
|
init: function(text, attributes) {
|
|
|
|
|
Sao.View.Form.Label._super.init.call(this, attributes);
|
|
|
|
|
this.el = jQuery('<label/>', {
|
|
|
|
|
text: text,
|
|
|
|
|
'class': 'form-label'
|
|
|
|
|
});
|
2013-05-06 15:03:25 +02:00
|
|
|
},
|
|
|
|
|
set_state: function(record) {
|
|
|
|
|
Sao.View.Form.Label._super.set_state.call(this, record);
|
|
|
|
|
if ((this.attributes.string === undefined) &&
|
|
|
|
|
this.attributes.name) {
|
|
|
|
|
var text = '';
|
|
|
|
|
if (record) {
|
|
|
|
|
text = record.field_get_client(this.attributes.name) || '';
|
|
|
|
|
}
|
|
|
|
|
this.el.val(text);
|
|
|
|
|
}
|
2013-02-04 18:23:30 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-02-05 12:39:19 +01:00
|
|
|
Sao.View.Form.Notebook = Sao.class_(StateWidget, {
|
|
|
|
|
init: function(attributes) {
|
|
|
|
|
Sao.View.Form.Notebook._super.init.call(this, attributes);
|
|
|
|
|
this.el = jQuery('<div/>', {
|
|
|
|
|
'class': 'form-notebook'
|
|
|
|
|
});
|
|
|
|
|
this.el.append(jQuery('<ul/>'));
|
|
|
|
|
this.el.tabs();
|
|
|
|
|
this.selected = false;
|
|
|
|
|
this.counter = 0;
|
|
|
|
|
},
|
|
|
|
|
add: function(tab, text) {
|
|
|
|
|
var tab_id = '#tab-form-' + this.counter++;
|
|
|
|
|
this.el.tabs('add', tab_id, text);
|
|
|
|
|
this.el.children(tab_id).html(tab);
|
|
|
|
|
if (!this.selected) {
|
|
|
|
|
this.el.tabs('select', tab_id);
|
|
|
|
|
this.selected = true;
|
|
|
|
|
}
|
2013-05-06 15:03:25 +02:00
|
|
|
return jQuery('> ul li', this.el).last();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Page = Sao.class_(StateWidget, {
|
|
|
|
|
init: function(el, attributes) {
|
|
|
|
|
Sao.View.Form.Page._super.init.call(this, attributes);
|
|
|
|
|
this.el = el;
|
2013-02-05 12:39:19 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-02-05 15:52:31 +01:00
|
|
|
Sao.View.Form.Group = Sao.class_(StateWidget, {
|
|
|
|
|
init: function(attributes) {
|
|
|
|
|
Sao.View.Form.Group._super.init.call(this, attributes);
|
|
|
|
|
this.el = jQuery('<div/>', {
|
|
|
|
|
'class': 'form-group'
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
add: function(widget) {
|
|
|
|
|
this.el.append(widget.el);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-02-04 18:23:30 +01:00
|
|
|
Sao.View.form_widget_get = function(type) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'char':
|
|
|
|
|
return Sao.View.Form.Char;
|
|
|
|
|
case 'sha':
|
|
|
|
|
return Sao.View.Form.Sha;
|
2013-02-06 17:34:32 +01:00
|
|
|
case 'date':
|
|
|
|
|
return Sao.View.Form.Date;
|
|
|
|
|
case 'integer':
|
|
|
|
|
case 'biginteger':
|
|
|
|
|
return Sao.View.Form.Integer;
|
|
|
|
|
case 'float':
|
|
|
|
|
case 'numeric':
|
|
|
|
|
return Sao.View.Form.Float;
|
|
|
|
|
case 'selection':
|
|
|
|
|
return Sao.View.Form.Selection;
|
|
|
|
|
case 'float_time':
|
|
|
|
|
return Sao.View.Form.FloatTime;
|
|
|
|
|
case 'boolean':
|
|
|
|
|
return Sao.View.Form.Boolean;
|
|
|
|
|
case 'text':
|
|
|
|
|
return Sao.View.Form.Text;
|
2013-04-18 13:07:21 +02:00
|
|
|
case 'many2one':
|
|
|
|
|
return Sao.View.Form.Many2One;
|
2013-02-04 18:23:30 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Widget = Sao.class_(Object, {
|
|
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
this.field_name = field_name;
|
|
|
|
|
this.model = model;
|
|
|
|
|
this.view = null; // Filled later
|
|
|
|
|
this.attributes = attributes;
|
|
|
|
|
this.el = null;
|
|
|
|
|
this.position = 0;
|
2013-05-06 15:03:25 +02:00
|
|
|
this.visible = true;
|
2013-02-04 18:23:30 +01:00
|
|
|
},
|
|
|
|
|
display: function(record, field) {
|
2013-05-06 15:03:25 +02:00
|
|
|
var readonly = this.attributes.readonly;
|
|
|
|
|
var invisible = this.attributes.invisible;
|
|
|
|
|
if (!field) {
|
|
|
|
|
if (readonly === undefined) {
|
|
|
|
|
readonly = true;
|
|
|
|
|
}
|
|
|
|
|
if (invisible === undefined) {
|
|
|
|
|
invisible = false;
|
|
|
|
|
}
|
|
|
|
|
this.set_readonly(readonly);
|
|
|
|
|
this.set_invisible(invisible);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (readonly === undefined) {
|
|
|
|
|
readonly = field.get_state_attrs(record).readonly;
|
|
|
|
|
if (readonly === undefined) {
|
|
|
|
|
readonly = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.set_readonly(readonly);
|
|
|
|
|
// TODO color
|
|
|
|
|
if (invisible === undefined) {
|
|
|
|
|
invisible = field.get_state_attrs(record).invisible;
|
|
|
|
|
if (invisible === undefined) {
|
|
|
|
|
invisible = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.set_invisible(invisible);
|
2013-02-21 14:16:19 +01:00
|
|
|
},
|
|
|
|
|
record: function() {
|
|
|
|
|
if (this.view && this.view.screen) {
|
|
|
|
|
return this.view.screen.current_record;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
field: function() {
|
|
|
|
|
var record = this.record();
|
|
|
|
|
if (record) {
|
|
|
|
|
return record.model.fields[this.field_name];
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
focus_out: function() {
|
|
|
|
|
if (!this.field()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-05-06 15:03:25 +02:00
|
|
|
if (!this.visible) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-02-21 14:16:19 +01:00
|
|
|
this.set_value(this.record(), this.field());
|
|
|
|
|
},
|
|
|
|
|
set_value: function(record, field) {
|
2013-05-06 15:03:25 +02:00
|
|
|
},
|
|
|
|
|
set_readonly: function(readonly) {
|
|
|
|
|
this.el.prop('disabled', readonly);
|
|
|
|
|
},
|
|
|
|
|
set_invisible: function(invisible) {
|
|
|
|
|
this.visible = !invisible;
|
|
|
|
|
if (invisible) {
|
|
|
|
|
this.el.hide();
|
|
|
|
|
} else {
|
|
|
|
|
this.el.show();
|
|
|
|
|
}
|
2013-02-04 18:23:30 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Char = Sao.class_(Sao.View.Form.Widget, {
|
2013-02-06 17:34:32 +01:00
|
|
|
class_: 'form-char',
|
2013-02-04 18:23:30 +01:00
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.Char._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
|
|
|
|
this.el = jQuery('<input/>', {
|
|
|
|
|
'type': 'input',
|
2013-02-06 17:34:32 +01:00
|
|
|
'class': this.class_
|
2013-02-04 18:23:30 +01:00
|
|
|
});
|
2013-02-21 14:16:19 +01:00
|
|
|
this.el.change(this.focus_out.bind(this));
|
2013-02-04 18:23:30 +01:00
|
|
|
},
|
|
|
|
|
display: function(record, field) {
|
|
|
|
|
Sao.View.Form.Char._super.display.call(this, record, field);
|
2013-03-04 19:08:16 +01:00
|
|
|
if (record) {
|
|
|
|
|
var value = record.field_get_client(this.field_name);
|
|
|
|
|
this.el.val(value || '');
|
|
|
|
|
} else {
|
|
|
|
|
this.el.val('');
|
|
|
|
|
}
|
2013-02-21 14:16:19 +01:00
|
|
|
},
|
|
|
|
|
set_value: function(record, field) {
|
|
|
|
|
var value = this.el.val() || '';
|
|
|
|
|
field.set_client(record, value);
|
2013-02-04 18:23:30 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Sha = Sao.class_(Sao.View.Form.Char, {
|
2013-02-06 17:34:32 +01:00
|
|
|
class_: 'form-sha',
|
2013-02-04 18:23:30 +01:00
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.Sha._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
|
|
|
|
this.el.prop('type', 'password');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-02-06 17:34:32 +01:00
|
|
|
Sao.View.Form.Date = Sao.class_(Sao.View.Form.Widget, {
|
|
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.Date._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
2013-04-17 17:01:23 +02:00
|
|
|
this.el = jQuery('<div/>', {
|
2013-02-06 17:34:32 +01:00
|
|
|
'class': 'form-date'
|
|
|
|
|
});
|
2013-04-17 17:01:23 +02:00
|
|
|
this.date = jQuery('<input/>', {
|
|
|
|
|
'type': 'input'
|
|
|
|
|
});
|
|
|
|
|
this.el.append(this.date);
|
|
|
|
|
this.date.datepicker({
|
|
|
|
|
showOn: 'button'
|
|
|
|
|
});
|
|
|
|
|
this.date.next('button').text('').button({
|
|
|
|
|
icons: {
|
|
|
|
|
primary: 'ui-icon-calendar'
|
|
|
|
|
},
|
|
|
|
|
text: false
|
|
|
|
|
});
|
|
|
|
|
this.date.change(this.focus_out.bind(this));
|
2013-02-06 17:34:32 +01:00
|
|
|
},
|
|
|
|
|
display: function(record, field) {
|
|
|
|
|
Sao.View.Form.Date._super.display.call(this, record, field);
|
2013-03-04 19:08:16 +01:00
|
|
|
if (record) {
|
|
|
|
|
var value = record.field_get_client(this.field_name);
|
2013-04-17 17:01:23 +02:00
|
|
|
this.date.datepicker('setDate', value);
|
2013-03-04 19:08:16 +01:00
|
|
|
} else {
|
2013-04-17 17:01:23 +02:00
|
|
|
this.date.datepicker('setDate', null);
|
2013-03-04 19:08:16 +01:00
|
|
|
}
|
2013-02-21 14:16:19 +01:00
|
|
|
},
|
|
|
|
|
set_value: function(record, field) {
|
2013-04-17 17:01:23 +02:00
|
|
|
var value = this.date.datepicker('getDate');
|
2013-02-21 14:16:19 +01:00
|
|
|
field.set_client(record, value);
|
2013-02-06 17:34:32 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// TODO DateTime, Time
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Integer = Sao.class_(Sao.View.Form.Char, {
|
|
|
|
|
class_: 'form-integer',
|
|
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.Integer._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
|
|
|
|
this.el.css('text-align', 'right');
|
2013-02-21 14:16:19 +01:00
|
|
|
},
|
|
|
|
|
set_value: function(record, field) {
|
|
|
|
|
var value = Number(this.el.val());
|
|
|
|
|
field.set_client(record, value);
|
2013-02-06 17:34:32 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Float = Sao.class_(Sao.View.Form.Integer, {
|
|
|
|
|
class_: 'form-float'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Selection = Sao.class_(Sao.View.Form.Widget, {
|
|
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.Selection._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
|
|
|
|
this.el = jQuery('<select/>', {
|
|
|
|
|
'class': 'form-selection'
|
|
|
|
|
});
|
2013-02-21 14:16:19 +01:00
|
|
|
this.el.change(this.focus_out.bind(this));
|
2013-02-06 17:34:32 +01:00
|
|
|
Sao.common.selection_mixin.init.call(this);
|
|
|
|
|
this.init_selection();
|
|
|
|
|
},
|
|
|
|
|
init_selection: function(key) {
|
|
|
|
|
Sao.common.selection_mixin.init_selection.call(this, key,
|
|
|
|
|
this.set_selection.bind(this));
|
|
|
|
|
},
|
|
|
|
|
update_selection: function(record, field, callbak) {
|
|
|
|
|
Sao.common.selection_mixin.update_selection.call(this, record,
|
|
|
|
|
field, function(selection) {
|
|
|
|
|
this.set_selection(selection);
|
|
|
|
|
if (callbak) {
|
|
|
|
|
callbak();
|
|
|
|
|
}
|
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
|
|
|
|
set_selection: function(selection) {
|
|
|
|
|
var select = this.el;
|
|
|
|
|
select.empty();
|
|
|
|
|
selection.forEach(function(e) {
|
|
|
|
|
select.append(jQuery('<option/>', {
|
|
|
|
|
'value': e[0],
|
|
|
|
|
'text': e[1]
|
|
|
|
|
}));
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
display: function(record, field) {
|
2013-05-06 15:03:25 +02:00
|
|
|
Sao.View.Form.Selection._super.display.call(this, record, field);
|
2013-02-06 17:34:32 +01:00
|
|
|
this.update_selection(record, field, function() {
|
|
|
|
|
if (!field) {
|
|
|
|
|
this.el.val('');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var value = field.get(record);
|
|
|
|
|
if (value === null) {
|
|
|
|
|
value = '';
|
|
|
|
|
}
|
|
|
|
|
this.el.val('' + value);
|
|
|
|
|
}.bind(this));
|
2013-02-21 14:16:19 +01:00
|
|
|
},
|
|
|
|
|
value_get: function() {
|
|
|
|
|
var val = this.el.val();
|
|
|
|
|
if ('relation' in this.attributes) {
|
|
|
|
|
return parseInt(val, 10);
|
|
|
|
|
}
|
|
|
|
|
return val;
|
|
|
|
|
},
|
|
|
|
|
set_value: function(record, field) {
|
|
|
|
|
var value = this.value_get();
|
|
|
|
|
field.set_client(record, value);
|
2013-02-06 17:34:32 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.FloatTime = Sao.class_(Sao.View.Form.Char, {
|
|
|
|
|
class_: 'form-float-time',
|
|
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.FloatTime._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
|
|
|
|
this.el.css('text-align', 'right');
|
|
|
|
|
this.conv = null; // TODO
|
|
|
|
|
},
|
|
|
|
|
display: function(record, field) {
|
|
|
|
|
Sao.View.Form.FloatTime._super.display.call(this, record, field);
|
2013-03-04 19:08:16 +01:00
|
|
|
if (record) {
|
|
|
|
|
var value = record.field_get_client(this.field_name);
|
|
|
|
|
this.el.val(Sao.common.text_to_float_time(value, this.conv));
|
|
|
|
|
} else {
|
|
|
|
|
this.el.val('');
|
|
|
|
|
}
|
2013-02-06 17:34:32 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Boolean = Sao.class_(Sao.View.Form.Widget, {
|
|
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.Boolean._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
|
|
|
|
this.el = jQuery('<input/>', {
|
|
|
|
|
'type': 'checkbox',
|
|
|
|
|
'class': 'form-boolean'
|
|
|
|
|
});
|
2013-02-21 14:16:19 +01:00
|
|
|
this.el.change(this.focus_out.bind(this));
|
2013-02-06 17:34:32 +01:00
|
|
|
},
|
|
|
|
|
display: function(record, field) {
|
|
|
|
|
Sao.View.Form.Boolean._super.display.call(this, record, field);
|
2013-03-04 19:08:16 +01:00
|
|
|
if (record) {
|
|
|
|
|
this.el.prop('checked', record.field_get(this.field_name));
|
|
|
|
|
} else {
|
|
|
|
|
this.el.prop('checked', false);
|
|
|
|
|
}
|
2013-02-21 14:16:19 +01:00
|
|
|
},
|
|
|
|
|
set_value: function(record, field) {
|
|
|
|
|
var value = this.el.prop('checked');
|
|
|
|
|
field.set_client(record, value);
|
2013-02-06 17:34:32 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Sao.View.Form.Text = Sao.class_(Sao.View.Form.Widget, {
|
|
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.Text._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
|
|
|
|
this.el = jQuery('<textarea/>', {
|
|
|
|
|
'class': 'form-text'
|
|
|
|
|
});
|
2013-02-21 14:16:19 +01:00
|
|
|
this.el.change(this.focus_out.bind(this));
|
2013-02-06 17:34:32 +01:00
|
|
|
},
|
|
|
|
|
display: function(record, field) {
|
|
|
|
|
Sao.View.Form.Text._super.display.call(this, record, field);
|
2013-03-04 19:08:16 +01:00
|
|
|
if (record) {
|
|
|
|
|
var value = record.field_get_client(this.field_name);
|
|
|
|
|
this.el.val(value);
|
|
|
|
|
} else {
|
|
|
|
|
this.el.val('');
|
|
|
|
|
}
|
2013-02-21 14:16:19 +01:00
|
|
|
},
|
|
|
|
|
set_value: function(record, field) {
|
|
|
|
|
var value = this.el.val() || '';
|
|
|
|
|
field.set_client(record, value);
|
2013-02-06 17:34:32 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-04-18 13:07:21 +02:00
|
|
|
Sao.View.Form.Many2One = Sao.class_(Sao.View.Form.Widget, {
|
|
|
|
|
class_: 'form-many2one',
|
|
|
|
|
init: function(field_name, model, attributes) {
|
|
|
|
|
Sao.View.Form.Many2One._super.init.call(this, field_name, model,
|
|
|
|
|
attributes);
|
|
|
|
|
this.el = jQuery('<div/>', {
|
|
|
|
|
'class': this.class_
|
|
|
|
|
});
|
|
|
|
|
this.entry = jQuery('<input/>', {
|
|
|
|
|
'type': 'input'
|
|
|
|
|
});
|
2013-05-10 17:48:20 +02:00
|
|
|
this.entry.on('keyup', this.key_press.bind(this));
|
2013-04-18 13:07:21 +02:00
|
|
|
this.el.append(this.entry);
|
|
|
|
|
this.but_open = jQuery('<button/>').button({
|
|
|
|
|
'icons': {
|
2013-05-10 18:24:26 +02:00
|
|
|
'primary': 'ui-icon-search'
|
2013-04-18 13:07:21 +02:00
|
|
|
},
|
|
|
|
|
'text': false
|
|
|
|
|
});
|
|
|
|
|
this.but_open.click(this.edit.bind(this));
|
|
|
|
|
this.el.append(this.but_open);
|
|
|
|
|
this.but_new = jQuery('<button/>').button({
|
|
|
|
|
'icons': {
|
2013-05-10 18:24:26 +02:00
|
|
|
'primary': 'ui-icon-document'
|
2013-04-18 13:07:21 +02:00
|
|
|
},
|
|
|
|
|
'text': false
|
|
|
|
|
});
|
|
|
|
|
this.but_new.click(this.new_.bind(this));
|
|
|
|
|
this.el.append(this.but_new);
|
|
|
|
|
this.model = attributes.relation;
|
|
|
|
|
// TODO autocompletion
|
|
|
|
|
},
|
|
|
|
|
get_screen: function() {
|
|
|
|
|
var domain = this.field().get_domain(this.record());
|
|
|
|
|
var context = this.field().get_context(this.record());
|
|
|
|
|
return new Sao.Screen(this.get_model(), {
|
|
|
|
|
'context': context,
|
|
|
|
|
'domain': domain,
|
|
|
|
|
'mode': ['form'],
|
2013-05-10 18:24:26 +02:00
|
|
|
'view_ids': (this.attributes.view_ids || '').split(','),
|
2013-04-18 13:07:21 +02:00
|
|
|
'views_preload': this.attributes.views
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
display: function(record, field) {
|
|
|
|
|
var text_value, value;
|
|
|
|
|
Sao.View.Form.Many2One._super.display.call(this, record, field);
|
2013-05-06 15:03:25 +02:00
|
|
|
|
|
|
|
|
this._set_button_sensitive();
|
|
|
|
|
|
2013-04-18 13:07:21 +02:00
|
|
|
if (record) {
|
|
|
|
|
text_value = record.field_get_client(this.field_name);
|
|
|
|
|
value = record.field_get(this.field_name);
|
|
|
|
|
} else {
|
|
|
|
|
this.entry.val('');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.entry.val(text_value || '');
|
|
|
|
|
if (this.has_target(value)) {
|
|
|
|
|
this.but_open.button({
|
|
|
|
|
'icons': {
|
2013-05-10 18:24:26 +02:00
|
|
|
'primary': 'ui-icon-folder-open'
|
2013-04-18 13:07:21 +02:00
|
|
|
}});
|
|
|
|
|
} else {
|
|
|
|
|
this.but_open.button({
|
|
|
|
|
'icons': {
|
2013-05-10 18:24:26 +02:00
|
|
|
'primary': 'ui-icon-search'
|
2013-04-18 13:07:21 +02:00
|
|
|
}});
|
|
|
|
|
}
|
|
|
|
|
},
|
2013-05-06 15:03:25 +02:00
|
|
|
set_readonly: function(readonly) {
|
|
|
|
|
this.entry.prop('disabled', readonly);
|
|
|
|
|
this._set_button_sensitive();
|
|
|
|
|
},
|
|
|
|
|
_set_button_sensitive: function() {
|
|
|
|
|
// TODO model access
|
|
|
|
|
var readonly = this.entry.prop('disabled');
|
|
|
|
|
var create = this.attributes.create;
|
|
|
|
|
if (create === undefined) {
|
|
|
|
|
create = true;
|
|
|
|
|
}
|
|
|
|
|
this.but_new.prop('disabled', readonly && create); // TODO access
|
|
|
|
|
// TODO but_open
|
|
|
|
|
},
|
2013-05-10 18:24:26 +02:00
|
|
|
id_from_value: function(value) {
|
2013-04-18 13:07:21 +02:00
|
|
|
return value;
|
|
|
|
|
},
|
2013-05-10 18:24:26 +02:00
|
|
|
value_from_id: function(id, str) {
|
2013-04-18 13:07:21 +02:00
|
|
|
if (str === undefined) {
|
|
|
|
|
str = '';
|
|
|
|
|
}
|
|
|
|
|
return [id, str];
|
|
|
|
|
},
|
2013-05-10 18:24:26 +02:00
|
|
|
get_model: function(value) {
|
2013-04-18 13:07:21 +02:00
|
|
|
return this.attributes.relation;
|
|
|
|
|
},
|
2013-05-10 18:24:26 +02:00
|
|
|
has_target: function(value) {
|
2013-04-18 13:07:21 +02:00
|
|
|
return value !== undefined && value !== null;
|
|
|
|
|
},
|
|
|
|
|
edit: function(evt) {
|
|
|
|
|
// TODO Model Access
|
|
|
|
|
var win;
|
|
|
|
|
var record = this.record();
|
|
|
|
|
var value = record.field_get(this.field_name);
|
|
|
|
|
if (this.get_model() && this.has_target(value)) {
|
|
|
|
|
var screen = this.get_screen();
|
|
|
|
|
var m2o_id =
|
|
|
|
|
this.id_from_value(record.field_get(this.field_name));
|
|
|
|
|
screen.new_group([m2o_id]);
|
2013-05-10 18:24:26 +02:00
|
|
|
var callback = function(result) {
|
2013-04-18 13:07:21 +02:00
|
|
|
if (result) {
|
|
|
|
|
var rec_name_prm = screen.current_record.rec_name();
|
2013-05-10 18:24:26 +02:00
|
|
|
rec_name_prm.done(function(name) {
|
2013-04-18 13:07:21 +02:00
|
|
|
var value = this.value_from_id(
|
|
|
|
|
screen.current_record.id, name);
|
|
|
|
|
this.record().field_set_client(this.field_name,
|
|
|
|
|
value, true);
|
|
|
|
|
}.bind(this));
|
|
|
|
|
}
|
2013-05-10 18:24:26 +02:00
|
|
|
};
|
|
|
|
|
win = new Sao.Window.Form(screen, callback.bind(this), {
|
2013-04-18 13:07:21 +02:00
|
|
|
save_current: true
|
|
|
|
|
});
|
|
|
|
|
} else if (this.get_model()) {
|
|
|
|
|
var dom;
|
|
|
|
|
var domain = this.field().get_domain(record);
|
|
|
|
|
var context = this.field().get_context(record);
|
|
|
|
|
var text = this.entry.val();
|
|
|
|
|
if (text) {
|
2013-05-10 18:24:26 +02:00
|
|
|
dom = [['rec_name', 'ilike', '%' + text + '%']];
|
2013-04-18 13:07:21 +02:00
|
|
|
} else {
|
|
|
|
|
dom = domain;
|
|
|
|
|
}
|
|
|
|
|
var model = new Sao.Model(this.get_model());
|
|
|
|
|
var ids_prm = model.execute('search',
|
|
|
|
|
[dom, 0, Sao.config.limit, null], context);
|
2013-05-10 18:24:26 +02:00
|
|
|
ids_prm.done(function(ids) {
|
2013-04-18 13:07:21 +02:00
|
|
|
if (ids.length == 1) {
|
|
|
|
|
this.record().field_set_client(this.field_name,
|
|
|
|
|
this.id_from_value(ids[0]), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-05-10 18:24:26 +02:00
|
|
|
var callback = function(result) {
|
2013-04-18 17:23:31 +02:00
|
|
|
if (!jQuery.isEmptyObject(result)) {
|
2013-04-18 13:07:21 +02:00
|
|
|
var value = this.value_from_id(result[0][0],
|
|
|
|
|
result[0][1]);
|
|
|
|
|
this.record().field_set_client(this.field_name,
|
|
|
|
|
value, true);
|
|
|
|
|
}
|
2013-05-10 18:24:26 +02:00
|
|
|
};
|
|
|
|
|
win = new Sao.Window.Search(this.model,
|
|
|
|
|
callback.bind(this), {
|
|
|
|
|
sel_multi: false,
|
|
|
|
|
ids: ids,
|
|
|
|
|
context: context,
|
|
|
|
|
domain: domain,
|
|
|
|
|
view_ids: (this.attributes.view_ids ||
|
|
|
|
|
'').split(','),
|
|
|
|
|
views_preload: (this.attributes.views || {}),
|
2013-05-14 19:15:37 +02:00
|
|
|
new_: !this.but_new.prop('disabled')
|
2013-04-18 13:07:21 +02:00
|
|
|
});
|
|
|
|
|
}.bind(this));
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
new_: function(evt) {
|
|
|
|
|
// TODO Model Access
|
|
|
|
|
var screen = this.get_screen();
|
2013-05-10 18:24:26 +02:00
|
|
|
var callback = function(result) {
|
2013-04-18 13:07:21 +02:00
|
|
|
if (result) {
|
|
|
|
|
var rec_name_prm = screen.current_record.rec_name();
|
2013-05-10 18:24:26 +02:00
|
|
|
rec_name_prm.done(function(name) {
|
2013-04-18 13:07:21 +02:00
|
|
|
var value = this.value_from_id(
|
|
|
|
|
screen.current_record.id, name);
|
|
|
|
|
this.record().field_set_client(this.field_name, value);
|
|
|
|
|
}.bind(this));
|
|
|
|
|
}
|
2013-05-10 18:24:26 +02:00
|
|
|
};
|
|
|
|
|
var win = new Sao.Window.Form(screen, callback.bind(this), {
|
2013-04-18 13:07:21 +02:00
|
|
|
new_: true,
|
|
|
|
|
save_current: true
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
key_press: function(event_) {
|
|
|
|
|
var editable = true; // TODO compute editable
|
|
|
|
|
var activate_keys = [Sao.common.TAB_KEYCODE];
|
|
|
|
|
var delete_keys = [Sao.common.BACKSPACE_KEYCODE,
|
|
|
|
|
Sao.common.DELETE_KEYCODE];
|
|
|
|
|
if (!this.wid_completion) {
|
|
|
|
|
activate_keys.push(Sao.common.RETURN_KEYCODE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (event_.which == Sao.common.F3_KEYCODE && editable) {
|
|
|
|
|
this.new_();
|
|
|
|
|
event_.preventDefault();
|
|
|
|
|
} else if (event_.which == Sao.common.F2_KEYCODE) {
|
|
|
|
|
this.edit();
|
|
|
|
|
event_.preventDefault();
|
|
|
|
|
} else if (jQuery.inArray(event_.which, activate_keys) > -1) {
|
|
|
|
|
this.activate();
|
|
|
|
|
} else if (this.has_target(this.record().field_get(
|
2013-05-10 17:48:20 +02:00
|
|
|
this.field_name)) && editable) {
|
|
|
|
|
var value = this.record().field_get_client(this.field_name);
|
|
|
|
|
if ((value != this.entry.val()) ||
|
|
|
|
|
(jQuery.inArray(event_.which, delete_keys) > -1)) {
|
|
|
|
|
this.entry.val('');
|
|
|
|
|
this.record().field_set_client(this.field_name,
|
|
|
|
|
this.value_from_id(null, ''));
|
|
|
|
|
}
|
2013-04-18 13:07:21 +02:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
activate: function() {
|
|
|
|
|
// TODO Model Access
|
|
|
|
|
var record = this.record();
|
|
|
|
|
var value = record.field_get(this.field_name);
|
|
|
|
|
var model = this.get_model();
|
|
|
|
|
var sao_model = new Sao.Model(model);
|
|
|
|
|
|
|
|
|
|
if (model && !this.has_target(value)) {
|
|
|
|
|
var text = this.entry.val();
|
|
|
|
|
if (!this._readonly && text) { // Check required
|
|
|
|
|
var dom;
|
|
|
|
|
var domain = this.field().get_domain(record);
|
|
|
|
|
var context = this.field().get_context(record);
|
|
|
|
|
|
|
|
|
|
if (text) {
|
2013-05-10 18:24:26 +02:00
|
|
|
dom = [['rec_name', 'ilike', '%' + text + '%']];
|
2013-04-18 13:07:21 +02:00
|
|
|
} else {
|
|
|
|
|
dom = domain;
|
|
|
|
|
}
|
|
|
|
|
var ids_prm = sao_model.execute('search',
|
|
|
|
|
[dom, 0, Sao.config.limit, null], context);
|
2013-05-10 18:24:26 +02:00
|
|
|
ids_prm.done(function(ids) {
|
2013-04-18 13:07:21 +02:00
|
|
|
if (ids.length == 1) {
|
2013-05-10 17:48:20 +02:00
|
|
|
Sao.rpc({
|
|
|
|
|
'method': 'model.' + model + '.read',
|
2013-05-10 18:24:26 +02:00
|
|
|
'params': [[this.id_from_value(ids[0])],
|
|
|
|
|
['rec_name'], context]
|
2013-05-10 17:48:20 +02:00
|
|
|
}, this.record().model.session
|
|
|
|
|
).then(function(values) {
|
|
|
|
|
this.record().field_set_client(this.field_name,
|
|
|
|
|
this.value_from_id(ids[0],
|
|
|
|
|
values[0].rec_name), true);
|
|
|
|
|
}.bind(this));
|
2013-04-18 13:07:21 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2013-05-10 18:24:26 +02:00
|
|
|
var callback = function(result) {
|
2013-04-18 17:23:31 +02:00
|
|
|
if (!jQuery.isEmptyObject(result)) {
|
2013-04-18 13:07:21 +02:00
|
|
|
var value = this.value_from_id(result[0][0],
|
|
|
|
|
result[0][1]);
|
|
|
|
|
this.record().field_set_client(this.field_name,
|
|
|
|
|
value, true);
|
|
|
|
|
} else {
|
|
|
|
|
this.entry.val('');
|
|
|
|
|
}
|
2013-05-10 18:24:26 +02:00
|
|
|
};
|
|
|
|
|
var win = new Sao.Window.Search(model,
|
|
|
|
|
callback.bind(this), {
|
|
|
|
|
sel_multi: false,
|
|
|
|
|
ids: ids,
|
|
|
|
|
context: context,
|
|
|
|
|
domain: domain,
|
|
|
|
|
view_ids: (this.attributes.view_ids ||
|
|
|
|
|
'').split(','),
|
|
|
|
|
views_preload: (this.attributes.views ||
|
|
|
|
|
{}),
|
|
|
|
|
new_: false
|
|
|
|
|
// TODO compute from but_new status
|
|
|
|
|
});
|
2013-04-18 13:07:21 +02:00
|
|
|
}.bind(this));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-01-04 21:29:48 +01:00
|
|
|
}());
|