diff --git a/CHANGELOG b/CHANGELOG index 469c01bd16..dec0d0f9ad 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Use separate XML parser in Views * Add range selection with Shift-click * Use between numbers in filter box * Fill 'to' with 'from' value on filter box diff --git a/src/view.js b/src/view.js index 292399c884..fa9753c8cd 100644 --- a/src/view.js +++ b/src/view.js @@ -4,12 +4,17 @@ 'use strict'; Sao.View = Sao.class_(Object, { + view_type: null, + el: null, + mnemonic_widget: null, + view_id: null, + editable: null, + children_field: null, + xml_parser: null, init: function(screen, xml) { this.screen = screen; - this.view_type = null; - this.el = null; - this.view_id = null; - this.fields = {}; + this.widgets = {}; + this.state_widgets = []; var attributes = xml.children()[0].attributes; this.attributes = {}; for (var i = 0, len = attributes.length; i < len; i++) { @@ -17,6 +22,18 @@ this.attributes[attribute.name] = attribute.value; } screen.set_on_write(this.attributes.on_write); + + var field_attrs = {}; + for (var name in this.screen.model.fields) { + field_attrs[name] = this.screen.model.fields[name].description; + } + new this.xml_parser( + this, this.screen.exclude_field, field_attrs) + .parse(xml.children()[0]); + }, + set_value: function() { + }, + get_fields: function() { }, get record() { return this.screen.current_record; @@ -27,17 +44,12 @@ get group() { return this.screen.group; }, - set_value: function() { - }, - get_fields: function() { - return Object.keys(this.fields); - }, get selected_records() { return []; }, get_buttons: function() { return []; - } + }, }); Sao.View.idpath2path = function(tree, idpath) { @@ -70,4 +82,68 @@ return new Sao.View.Calendar(screen, xml); } }; + + Sao.View.XMLViewParser = Sao.class_(Object, { + init: function(view, exclude_field, field_attrs) { + this.view = view; + this.exclude_field = exclude_field; + this.field_attrs = field_attrs; + }, + _node_attributes: function(node) { + var node_attrs = {}; + for (var i = 0; i < node.attributes.length; i++) { + var attribute = node.attributes[i]; + node_attrs[attribute.name] = attribute.value; + } + + var field = {}; + if (node_attrs.name) { + field = this.field_attrs[node_attrs.name] || {}; + } + + ['readonly', 'homogeneous'].forEach(function(name) { + if (node_attrs[name]) { + node_attrs[name] = node_attrs[name] == 1; + } + }); + ['yexpand', 'yfill', 'xexpand', 'xfill', 'colspan', + 'position'].forEach(function(name) { + if (node_attrs[name]) { + node_attrs[name] = Number(node_attrs[name]); + } + }); + ['xalign', 'yalign'].forEach(function(name) { + if (node_attrs[name]) { + node_attrs[name] = Number(node_attrs[name]); + } + }); + + if (!jQuery.isEmptyObject(field)) { + if (!node_attrs.widget) { + node_attrs.widget = field.type; + } + if ((node.tagName == 'label') && (!node_attrs.string)) { + node_attrs.string = field.string + Sao.i18n.gettext(':'); + } + if ((node.tagName == 'field') && (!node_attrs.help)) { + node_attrs.help = field.help; + } + + ['relation', 'domain', 'selection', 'string', 'states', + 'relation_field', 'views', 'invisible', 'add_remove', + 'sort', 'context', 'size', 'filename', 'autocomplete', + 'translate', 'create', 'delete', 'selection_change_with', + 'schema_model'].forEach(function(name) { + if (field[name] && !node_attrs[name]) { + node_attrs[name] = field[name]; + } + }); + } + return node_attrs; + }, + parse: function(node) { + var attributes = this._node_attributes(node); + this['_parse_' + node.tagName](node, attributes); + }, + }); }()); diff --git a/src/view/calendar.js b/src/view/calendar.js index ef806b801e..71a674e22c 100644 --- a/src/view/calendar.js +++ b/src/view/calendar.js @@ -3,27 +3,27 @@ (function() { 'use strict'; - Sao.View.Calendar = Sao.class_(Sao.View, { - /* Fullcalendar works with utc date, the default week start day depends on - the user language, the events dates are handled by moment object. */ - init: function(screen, xml) { - Sao.View.Calendar._super.init.call(this, screen, xml); - // Used to check if the events are still processing - this.processing = true; - this.view_type = 'calendar'; - this.el = jQuery('
', { - 'class': 'calendar' - }); - var lang = Sao.i18n.getlang(); - lang = lang.slice(0, 2); + Sao.View.CalendarXMLViewParser = Sao.class_(Sao.View.XMLViewParser, { + _parse_calendar: function(node, attributes) { + [].forEach.call(node.childNodes, function(child) { + this.parse(child); + }.bind(this)); + + var view_week; + if (this.view.screen.model.fields[attributes.dtstart] + .description.type == "datetime") { + view_week = 'agendaWeek'; + } else { + view_week = 'basicWeek'; + } var defaultview = 'month'; - if (this.attributes.mode == 'week') { - defaultview = this.get_week_view(); + if (attributes.mode == 'week') { + defaultview = view_week; } var header = { left: 'today prev,next', center: 'title', - right: 'month,' + this.get_week_view(), + right: 'month,' + view_week, }; if (Sao.i18n.rtl) { var header_rtl = jQuery.extend({}, header); @@ -31,12 +31,12 @@ header_rtl.right = header.left; header = header_rtl; } - this.el.fullCalendar({ + this.view.el.fullCalendar({ defaultView: defaultview, header: header, timeFormat: 'H:mm', - events: this.get_events.bind(this), - locale: lang, + events: this.view.get_events.bind(this.view), + locale: Sao.i18n.getlang().slice(0, 2), isRTL: Sao.i18n.rtl, themeSystem: 'bootstrap3', bootstrapGlyphicons: { @@ -48,19 +48,33 @@ 'month': Sao.i18n.gettext("Month"), 'week': Sao.i18n.gettext("Week"), }, - eventRender: this.event_render.bind(this), - eventResize: this.event_resize.bind(this), - eventDrop: this.event_drop.bind(this), - eventClick: this.event_click.bind(this), - dayClick: this.day_click.bind(this), + eventRender: this.view.event_render.bind(this.view), + eventResize: this.view.event_resize.bind(this.view), + eventDrop: this.view.event_drop.bind(this.view), + eventClick: this.view.event_click.bind(this.view), + dayClick: this.view.day_click.bind(this.view), }); + }, + _parse_field: function(node, attributes) { + this.view.fields.push(attributes.name); + }, + }); + + Sao.View.Calendar = Sao.class_(Sao.View, { + /* Fullcalendar works with utc date, the default week start day depends on + the user language, the events dates are handled by moment object. */ + editable: false, + view_type: 'calendar', + xml_parser: Sao.View.CalendarXMLViewParser, + init: function(screen, xml) { + // Used to check if the events are still processing + this.processing = true; this.fields = []; - xml.find('calendar').children().each(function(pos, child){ - if (child.tagName == 'field') { - this.fields.push(child.attributes.name.value); - } - }.bind(this)); - this.el.fullCalendar('changeView', defaultview); + this.el = jQuery('', { + 'class': 'calendar' + }); + Sao.View.Calendar._super.init.call(this, screen, xml); + //this.el.fullCalendar('changeView', defaultview); }, get_colors: function(record) { var colors = {}; @@ -158,14 +172,6 @@ }.bind(this)); }.bind(this)); }, - get_week_view: function() { - if (this.screen.model.fields[this.attributes.dtstart] - .description.type == "datetime") { - return 'agendaWeek'; - } else { - return 'basicWeek'; - } - }, event_click: function(calEvent, jsEvent, view) { // Prevent opening the wrong event while the calendar event clicked // when loading diff --git a/src/view/form.js b/src/view/form.js index 42069a6afd..9b7ca79e39 100644 --- a/src/view/form.js +++ b/src/view/form.js @@ -14,236 +14,56 @@ function eval_pyson(value){ (function() { 'use strict'; - Sao.View.Form = Sao.class_(Sao.View, { - editable: true, - init: function(screen, xml) { - Sao.View.Form._super.init.call(this, screen, xml); - this.view_type = 'form'; - this.el = jQuery('', { - 'class': 'form' - }); - this.widgets = {}; - this.widget_id = 0; - this.state_widgets = []; - this.containers = []; - this.notebooks = []; - this.expandables = []; + Sao.View.FormXMLViewParser = Sao.class_(Sao.View.XMLViewParser, { + init: function(view, exclude_field, field_attrs) { + Sao.View.FormXMLViewParser._super.init.call( + this, view, exclude_field, field_attrs); + this._containers = []; + this._mnemonics = {}; + }, + get container() { + if (this._containers.length > 0) { + return this._containers[this._containers.length - 1]; + } + return null; + }, + _parse_form: function(node, attributes) { + var container = new Sao.View.Form.Container( + Number(node.getAttribute('col') || 4)); + this.view.containers.push(container); + this.view.el.append(container.el); + this.parse_child(node, container); + if (this._containers.length > 0) { + throw 'AssertionError'; + } + }, + parse_child: function(node, container) { + if (container) { + this._containers.push(container); + } + [].forEach.call(node.childNodes, function(child) { + this.parse(child); + }.bind(this)); + if (container) { + this._containers.pop(); + } + }, + _parse_field: function(node, attributes) { + var name = attributes.name; + if (name && (name == this.exclude_field)) { + this.container.add(null, attributes); + return; + } + var WidgetFactory = Sao.View.FormXMLViewParser.WIDGETS[ + attributes.widget]; + var widget = new WidgetFactory(this.view, attributes); + if (!this.view.widgets[name]) { + this.view.widgets[name] = []; + } + this.view.widgets[name].push(widget); + widget.position = this.view.widget_id += 1; - var root = xml.children()[0]; - var container = this.parse(screen.model, root); - this.el.append(container.el); - }, - _parse_node: function(model, child, container, attributes, labels) { - var widget; - switch (child.tagName) { - case 'image': - this._parse_image( - model, child, container, attributes); - break; - case 'separator': - this._parse_separator( - model, child, container, attributes); - break; - case 'label': - widget = this._parse_label( - model, child, container, attributes); - if (attributes.name && widget) { - labels[attributes.name] = widget; - } - break; - case 'newline': - container.add_row(); - break; - case 'button': - this._parse_button(child, container, attributes); - break; - case 'notebook': - this._parse_notebook( - model, child, container, attributes); - break; - case 'page': - this._parse_page(model, child, container, attributes); - break; - case 'field': - widget = this._parse_field( - model, child, container, attributes); - if ((attributes.name in labels) && - widget && - widget.labelled) { - var label = labels[attributes.name]; - label.el.uniqueId(); - widget.labelled.uniqueId(); - widget.labelled.attr( - 'aria-labelledby', label.el.attr('id')); - label.el.attr('for', widget.labelled.attr('id')); - } - break; - case 'group': - this._parse_group(model, child, container, attributes); - break; - case 'hpaned': - this._parse_paned(model, child, container, attributes, - 'horizontal'); - break; - case 'vpaned': - this._parse_paned(model, child, container, attributes, - 'vertical'); - break; - case 'child': - this._parse_child(model, child, container, attributes); - break; - } - }, - parse: function(model, node, container) { - if (container === undefined) { - container = new Sao.View.Form.Container( - Number(node.getAttribute('col') || 4)); - this.containers.push(container); - } - var labels = {}; - var _parse = function(index, child) { - var attributes = {}; - for (var i = 0, len = child.attributes.length; i < len; i++) { - var attribute = child.attributes[i]; - attributes[attribute.name] = attribute.value; - } - ['readonly', 'invisible'].forEach(function(name) { - if (attributes[name]) { - attributes[name] = attributes[name] == 1; - } - }); - ['yexpand', 'yfill', 'xexpand', 'xfill', 'colspan'].forEach( - function(name) { - if (attributes[name]) { - attributes[name] = Number(attributes[name]); - } - }); - this._parse_node(model, child, container, attributes, labels); - }; - jQuery(node).children().each(_parse.bind(this)); - return container; - }, - _parse_image: function(model, node, container, attributes) { - var image = new Sao.View.Form.Image_(attributes); - this.state_widgets.push(image); - container.add(attributes, image); - }, - _parse_separator: function(model, node, container, attributes) { - var name = attributes.name; - var text = attributes.string; - if (name in model.fields) { - if (!attributes.states && (name in model.fields)) { - attributes.states = model.fields[name].description.states; - } - if (!text) { - text = model.fields[name].description.string; - } - } - var separator = new Sao.View.Form.Separator(text, attributes); - this.state_widgets.push(separator); - container.add(attributes, separator); - }, - _parse_label: function(model, node, container, attributes) { - var name = attributes.name; - if (attributes.xexpand === undefined) { - attributes.xexpand = 0; - } - if (name in model.fields) { - if (name == this.screen.exclude_field) { - container.add(attributes); - return; - } - if (!attributes.states && (name in model.fields)) { - attributes.states = model.fields[name].description.states; - } - if (attributes.string === undefined) { - attributes.string = model.fields[name] - .description.string + Sao.i18n.gettext(':'); - } - } - if (attributes.xalign === undefined) { - attributes.xalign = 1.0; - } - var label = new Sao.View.Form.Label(attributes.string, attributes); - this.state_widgets.push(label); - container.add(attributes, label); - return label; - }, - _parse_button: function(node, container, attributes) { - var button = new Sao.common.Button(attributes); - this.state_widgets.push(button); - container.add(attributes, button); - button.el.click(button, this.button_clicked.bind(this)); - }, - _parse_notebook: function(model, node, container, attributes) { - if (attributes.colspan === undefined) { - attributes.colspan = 4; - } - var notebook = new Sao.View.Form.Notebook(attributes); - if (attributes.height) { - notebook.el.css('min-height', attributes.height + 'px'); - } - if (attributes.width) { - notebook.el.css('min-width', attributes.width + 'px'); - } - this.notebooks.push(notebook); - this.state_widgets.push(notebook); - container.add(attributes, notebook); - this.parse(model, node, notebook); - }, - _parse_page: function(model, node, container, attributes) { - var text = attributes.string; - if (attributes.name in model.fields) { - var field = model.fields[attributes.name]; - if (attributes.name == this.screen.exclude_field) { - return; - } - ['states', 'string'].forEach(function(attr) { - if ((attributes[attr] === undefined) && - (field.description[attr] !== undefined)) { - attributes[attr] = field.description[attr]; - } - }); - } - var page = this.parse(model, node); - page = new Sao.View.Form.Page( - container.add( - page.el, attributes.string, attributes.icon), - attributes); - this.state_widgets.push(page); - }, - _parse_field: function(model, node, container, attributes) { - var name = attributes.name; - if (!(name in model.fields) || name == this.screen.exclude_field) { - container.add(attributes); - return; - } - if (!attributes.widget) { - attributes.widget = model.fields[name] - .description.type; - } - var attribute_names = ['relation', 'domain', 'selection', 'help', - 'relation_field', 'string', 'views', 'add_remove', 'sort', - 'context', 'size', 'filename', 'autocomplete', 'translate', - 'create', 'delete', 'selection_change_with', 'schema_model']; - 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(attributes); - return; - } - var widget = new WidgetFactory(name, model, attributes); - widget.position = this.widget_id += 1; - widget.view = this; - if (WidgetFactory.prototype.expand) { + if (widget.expand) { if (attributes.yexpand === undefined) { attributes.yexpand = true; } @@ -251,62 +71,137 @@ function eval_pyson(value){ attributes.yfill = true; } } - if (attributes.height) { + + if (attributes.height !== undefined) { widget.el.css('min-height', attributes.height + 'px'); } if (attributes.width !== undefined) { widget.el.css('min-width', attributes.width + 'px'); } - container.add(attributes, widget); - if (this.widgets[name] === undefined) { - this.widgets[name] = []; + + this.container.add(widget, attributes); + + if (this._mnemonics[name] && widget.labelled) { + var label = this._mnemonics[name]; + label.el.uniqueId(); + widget.labelled.uniqueId(); + widget.labelled.attr('aria-labelledby', label.el.attr('id')); + label.el.attr('for', widget.labelled.attr('id')); } - this.widgets[name].push(widget); - this.fields[name] = true; - return widget; }, - _parse_group: function(model, node, container, attributes) { - if (attributes.name !== undefined) { - var field = model.fields[attributes.name]; - if (attributes.name == this.screen.exclude_field) { - container.add(attributes); - return; - } - ['states', 'string'].forEach(function(attr) { - if (!(attr in attributes) && (attr in field.description)) { - attributes[attr] = field.description[attr]; - } - }); + _parse_button: function(node, attributes) { + var button = new Sao.common.Button(attributes); + button.el.click(button, this.view.button_clicked.bind(this.view)); + this.view.state_widgets.push(button); + this.container.add(button, attributes); + }, + _parse_image: function(node, attributes) { + var image = new Sao.View.Form.Image_(attributes); + this.view.state_widgets.push(image); + this.container.add(image, attributes); + }, + _parse_separator: function(node, attributes) { + var text = attributes.string; + var separator = new Sao.View.Form.Separator(text, attributes); + this.view.state_widgets.push(separator); + this.container.add(separator, attributes); + }, + _parse_label: function(node, attributes) { + var name = attributes.name; + if (name && (name == this.exclude_field)) { + this.container.add(null, attributes); + return; + } + if (attributes.xexpand === undefined) { + attributes.xexpand = 0; + } + if (attributes.xalign === undefined) { + attributes.xalign = 1.0; + } + var label = new Sao.View.Form.Label(attributes.string, attributes); + this.view.state_widgets.push(label); + this.container.add(label, attributes); + if (name) { + this._mnemonics[name] = label; + } + }, + _parse_newline: function(node, attributes) { + this.container.add_row(); + }, + _parse_notebook: function(node, attributes) { + if (attributes.colspan === undefined) { + attributes.colspan = 4; + } + var notebook = new Sao.View.Form.Notebook(attributes); + if (attributes.height !== undefined) { + notebook.el.css('min-height', attributes.height + 'px'); + } + if (attributes.width !== undefined) { + notebook.el.css('min-width', attributes.width + 'px'); + } + this.view.state_widgets.push(notebook); + this.view.notebooks.push(notebook); + this.container.add(notebook, attributes); + this.parse_child(node, notebook); + }, + _parse_page: function(node, attributes) { + if (attributes.name && (attributes.name == this.exclude_field)) { + return; + } + var container = new Sao.View.Form.Container( + Number(node.getAttribute('col') || 4)); + this.view.containers.push(container); + this.parse_child(node, container); + var page = new Sao.View.Form.Page( + this.container.add( + container.el, attributes.string, attributes.icon), + attributes); + this.view.state_widgets.push(page); + }, + _parse_group: function(node, attributes) { + var group = new Sao.View.Form.Container( + Number(node.getAttribute('col') || 4)); + this.view.containers.push(group); + this.parse_child(node, group); + + if (attributes.name && (attributes.name == this.exclude_field)) { + this.container.add(null, attributes); + return; } var widget; if (attributes.expandable !== undefined) { widget = new Sao.View.Form.Expander(attributes); widget.set_expanded(attributes.expandable === '1'); - this.expandables.push(widget); + this.view.expandables.push(widget); } else { widget = new Sao.View.Form.Group(attributes); } - widget.add(this.parse(model, node)); + widget.add(group); - this.state_widgets.push(widget); - container.add(attributes, widget); + this.view.state_widgets.push(widget); + this.container.add(widget, attributes); }, - _parse_paned: function(model, node, container, attributes, - orientation) { - if (attributes.yexpand === undefined) { - attributes.yexpand = true; - } - if (attributes.yfill === undefined) { - attributes.yfill = true; - } + _parse_hpaned: function(node, attributes) { + this._parse_paned(node, attributes, 'horizontal'); + }, + _parse_vpaned: function(node, attributes) { + this._parse_paned(node, attributes, 'vertical'); + }, + _parse_paned: function(node, attributes, orientation) { var paned = new Sao.common.Paned(orientation); // TODO position - container.add(attributes, paned); - this.parse(model, node, paned); + this.view.containers.push(paned); + this.container.add(paned, attributes); + this.parse_child(node, paned); }, - _parse_child: function(model, node, paned, attributes) { - var container = this.parse(model, node); + _parse_child: function(node, attributes) { + var paned = this.container; + var container = new Sao.View.Form.Container( + Number(node.getAttribute('col') || 4)); + this.view.containers.push(container); + this.parse_child(node, container); + var child; if (!paned.get_child1().children().length) { child = paned.get_child1(); @@ -315,6 +210,22 @@ function eval_pyson(value){ } child.append(container.el); }, + }); + + Sao.View.Form = Sao.class_(Sao.View, { + editable: true, + view_type: 'form', + xml_parser: Sao.View.FormXMLViewParser, + init: function(screen, xml) { + this.el = jQuery('', { + 'class': 'form' + }); + this.notebooks = []; + this.expandables = []; + this.containers = []; + this.widget_id = 0; + Sao.View.Form._super.init.call(this, screen, xml); + }, get_buttons: function() { var buttons = []; for (var j in this.state_widgets) { @@ -521,7 +432,7 @@ function eval_pyson(value){ row: function() { return this.rows().last(); }, - add: function(attributes, widget) { + add: function(widget, attributes) { var colspan = attributes.colspan; if (colspan === undefined) colspan = 1; var xfill = attributes.xfill; @@ -958,75 +869,10 @@ function eval_pyson(value){ } }); - Sao.View.form_widget_get = function(type) { - switch (type) { - case 'char': - return Sao.View.Form.Char; - case 'password': - return Sao.View.Form.Password; - case 'date': - return Sao.View.Form.Date; - case 'datetime': - case 'timestamp': - return Sao.View.Form.DateTime; - case 'time': - return Sao.View.Form.Time; - case 'timedelta': - return Sao.View.Form.TimeDelta; - 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 'boolean': - return Sao.View.Form.Boolean; - case 'text': - return Sao.View.Form.Text; - case 'richtext': - return Sao.View.Form.RichText; - case 'many2one': - return Sao.View.Form.Many2One; - case 'one2one': - return Sao.View.Form.One2One; - case 'reference': - return Sao.View.Form.Reference; - case 'one2many': - return Sao.View.Form.One2Many; - case 'many2many': - return Sao.View.Form.Many2Many; - case 'binary': - return Sao.View.Form.Binary; - case 'multiselection': - return Sao.View.Form.MultiSelection; - case 'image': - return Sao.View.Form.Image; - case 'url': - return Sao.View.Form.URL; - case 'email': - return Sao.View.Form.Email; - case 'callto': - return Sao.View.Form.CallTo; - case 'sip': - return Sao.View.Form.SIP; - case 'progressbar': - return Sao.View.Form.ProgressBar; - case 'dict': - return Sao.View.Form.Dict; - case 'pyson': - return Sao.View.Form.PYSON; - } - }; - - Sao.View.Form.Widget = Sao.class_(Object, { expand: false, - init: function(field_name, model, attributes) { - this.field_name = field_name; - this.model = model; - this.view = null; // Filled later + init: function(view, attributes) { + this.view = view; this.attributes = attributes; this.el = null; this.position = 0; @@ -1104,6 +950,15 @@ function eval_pyson(value){ _invalid_el: function() { return this.el; }, + get field_name() { + return this.attributes.name; + }, + get model_name() { + return this.view.screen.model_name; + }, + get model() { + return this.view.screen.model; + }, get record() { return this.view.record; }, @@ -1353,9 +1208,8 @@ function eval_pyson(value){ Sao.View.Form.Char = Sao.class_(Sao.View.Form.Widget, { class_: 'form-char', - init: function(field_name, model, attributes) { - Sao.View.Form.Char._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Char._super.init.call(this, view, attributes); Sao.View.Form.TranslateMixin.init.call(this); this.el = jQuery('', { 'class': this.class_ @@ -1454,9 +1308,8 @@ function eval_pyson(value){ Sao.View.Form.Password = Sao.class_(Sao.View.Form.Char, { class_: 'form-password', - init: function(field_name, model, attributes) { - Sao.View.Form.Password._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Password._super.init.call(this, view, attributes); this.input.prop('type', 'password'); this.button = jQuery('', { 'class': 'btn btn-default btn-sm form-control', @@ -1490,9 +1343,8 @@ function eval_pyson(value){ Sao.View.Form.Date = Sao.class_(Sao.View.Form.Widget, { class_: 'form-date', _width: '10em', - init: function(field_name, model, attributes) { - Sao.View.Form.Date._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Date._super.init.call(this, view, attributes); this.el = jQuery('', { 'class': this.class_ }); @@ -1632,9 +1484,8 @@ function eval_pyson(value){ Sao.View.Form.TimeDelta = Sao.class_(Sao.View.Form.Widget, { class_: 'form-timedelta', - init: function(field_name, model, attributes) { - Sao.View.Form.TimeDelta._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.TimeDelta._super.init.call(this, view, attributes); this.el = jQuery('', { 'class': this.class_ }); @@ -1690,9 +1541,8 @@ function eval_pyson(value){ 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); + init: function(view, attributes) { + Sao.View.Form.Integer._super.init.call(this, view, attributes); this.input_text = integer_input(this.input); this.group.css('width', ''); this.factor = Number(attributes.factor || 1); @@ -1756,9 +1606,8 @@ function eval_pyson(value){ Sao.View.Form.Selection = Sao.class_(Sao.View.Form.Widget, { class_: 'form-selection', - init: function(field_name, model, attributes) { - Sao.View.Form.Selection._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Selection._super.init.call(this, view, attributes); this.el = jQuery('', { 'class': this.class_ }); @@ -1848,9 +1697,8 @@ function eval_pyson(value){ Sao.View.Form.Boolean = Sao.class_(Sao.View.Form.Widget, { class_: 'form-boolean', - init: function(field_name, model, attributes) { - Sao.View.Form.Boolean._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Boolean._super.init.call(this, view, attributes); this.el = jQuery('', { 'class': this.class_ }); @@ -1889,9 +1737,8 @@ function eval_pyson(value){ Sao.View.Form.Text = Sao.class_(Sao.View.Form.Widget, { class_: 'form-text', expand: true, - init: function(field_name, model, attributes) { - Sao.View.Form.Text._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Text._super.init.call(this, view, attributes); Sao.View.Form.TranslateMixin.init.call(this); this.el = jQuery('', { 'class': this.class_ @@ -1949,9 +1796,8 @@ function eval_pyson(value){ Sao.View.Form.RichText = Sao.class_(Sao.View.Form.Widget, { class_: 'form-richtext', expand: true, - init: function(field_name, model, attributes) { - Sao.View.Form.RichText._super.init.call( - this, field_name, model, attributes); + init: function(view, attributes) { + Sao.View.Form.RichText._super.init.call(this, view, attributes); Sao.View.Form.TranslateMixin.init.call(this); this.el = jQuery('', { 'class': this.class_ + ' panel panel-default' @@ -2194,9 +2040,8 @@ function eval_pyson(value){ 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); + init: function(view, attributes) { + Sao.View.Form.Many2One._super.init.call(this, view, attributes); this.el = jQuery('', { 'class': this.class_ }); @@ -2618,9 +2463,8 @@ function eval_pyson(value){ Sao.View.Form.Reference = Sao.class_(Sao.View.Form.Many2One, { class_: 'form-reference', - init: function(field_name, model, attributes) { - Sao.View.Form.Reference._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Reference._super.init.call(this, view, attributes); this.el.addClass('form-inline'); this.select = jQuery('', { 'class': 'form-control input-sm', @@ -2763,9 +2607,8 @@ function eval_pyson(value){ Sao.View.Form.One2Many = Sao.class_(Sao.View.Form.Widget, { class_: 'form-one2many', expand: true, - init: function(field_name, model, attributes) { - Sao.View.Form.One2Many._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.One2Many._super.init.call(this, view, attributes); this._readonly = true; this._required = false; @@ -3283,9 +3126,8 @@ function eval_pyson(value){ Sao.View.Form.Many2Many = Sao.class_(Sao.View.Form.Widget, { class_: 'form-many2many', expand: true, - init: function(field_name, model, attributes) { - Sao.View.Form.Many2Many._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Many2Many._super.init.call(this, view, attributes); this._readonly = true; this._required = false; @@ -3544,9 +3386,9 @@ function eval_pyson(value){ }); Sao.View.Form.BinaryMixin = Sao.class_(Sao.View.Form.Widget, { - init: function(field_name, model, attributes) { + init: function(view, attributes) { Sao.View.Form.BinaryMixin._super.init.call( - this, field_name, model, attributes); + this, view, attributes); this.filename = attributes.filename || null; }, toolbar: function(class_) { @@ -3659,9 +3501,8 @@ function eval_pyson(value){ Sao.View.Form.Binary = Sao.class_(Sao.View.Form.BinaryMixin, { class_: 'form-binary', blob_url: '', - init: function(field_name, model, attributes) { - Sao.View.Form.Binary._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.Binary._super.init.call(this, view, attributes); this.el = jQuery('', { 'class': this.class_ @@ -3757,10 +3598,10 @@ function eval_pyson(value){ Sao.View.Form.MultiSelection = Sao.class_(Sao.View.Form.Selection, { class_: 'form-multiselection', expand: true, - init: function(field_name, model, attributes) { + init: function(view, attributes) { this.nullable_widget = false; - Sao.View.Form.MultiSelection._super.init.call(this, field_name, - model, attributes); + Sao.View.Form.MultiSelection._super.init.call( + this, view, attributes); this.select.prop('multiple', true); }, display_update_selection: function(record, field) { @@ -3801,9 +3642,8 @@ function eval_pyson(value){ Sao.View.Form.Image = Sao.class_(Sao.View.Form.BinaryMixin, { class_: 'form-image', - init: function(field_name, model, attributes) { - Sao.View.Form.Image._super.init.call( - this, field_name, model, attributes); + init: function(view, attributes) { + Sao.View.Form.Image._super.init.call(this, view, attributes); this.height = parseInt(attributes.height || 100, 10); this.width = parseInt(attributes.width || 300, 10); @@ -3868,9 +3708,8 @@ function eval_pyson(value){ Sao.View.Form.URL = Sao.class_(Sao.View.Form.Char, { class_: 'form-url', - init: function(field_name, model, attributes) { - Sao.View.Form.URL._super.init.call( - this, field_name, model, attributes); + init: function(view, attributes) { + Sao.View.Form.URL._super.init.call(this, view, attributes); this.button = jQuery('', { 'class': 'btn btn-default', 'target': '_new' @@ -3946,9 +3785,9 @@ function eval_pyson(value){ Sao.View.Form.ProgressBar = Sao.class_(Sao.View.Form.Widget, { class_: 'form-char', - init: function(field_name, model, attributes) { + init: function(view, attributes) { Sao.View.Form.ProgressBar._super.init.call( - this, field_name, model, attributes); + this, view, attributes); this.el = jQuery('', { 'class': this.class_ + ' progress' }); @@ -3984,9 +3823,8 @@ function eval_pyson(value){ Sao.View.Form.Dict = Sao.class_(Sao.View.Form.Widget, { class_: 'form-dict', expand: true, - init: function(field_name, model, attributes) { - Sao.View.Form.Dict._super.init.call( - this, field_name, model, attributes); + init: function(view, attributes) { + Sao.View.Form.Dict._super.init.call(this, view, attributes); this.schema_model = attributes.schema_model; this.fields = {}; @@ -4500,9 +4338,8 @@ function eval_pyson(value){ Sao.View.Form.PYSON = Sao.class_(Sao.View.Form.Char, { class_: 'form-pyson', - init: function(field_name, model, attributes) { - Sao.View.Form.PYSON._super.init.call(this, field_name, model, - attributes); + init: function(view, attributes) { + Sao.View.Form.PYSON._super.init.call(this, view, attributes); this.encoder = new Sao.PYSON.Encoder({}); this.decoder = new Sao.PYSON.Decoder({}, true); this.el.keyup(this.validate_pyson.bind(this)); @@ -4562,4 +4399,36 @@ function eval_pyson(value){ } }); + Sao.View.FormXMLViewParser.WIDGETS = { + 'biginteger': Sao.View.Form.Integer, + 'binary': Sao.View.Form.Binary, + 'boolean': Sao.View.Form.Boolean, + 'callto': Sao.View.Form.CallTo, + 'char': Sao.View.Form.Char, + 'date': Sao.View.Form.Date, + 'datetime': Sao.View.Form.DateTime, + 'dict': Sao.View.Form.DictWidget, + 'email': Sao.View.Form.Email, + 'float': Sao.View.Form.Float, + 'image': Sao.View.Form.Image, + 'integer': Sao.View.Form.Integer, + 'many2many': Sao.View.Form.Many2Many, + 'many2one': Sao.View.Form.Many2One, + 'multiselection': Sao.View.Form.MultiSelection, + 'numeric': Sao.View.Form.Float, + 'one2many': Sao.View.Form.One2Many, + 'one2one': Sao.View.Form.One2One, + 'password': Sao.View.Form.Password, + 'progressbar': Sao.View.Form.ProgressBar, + 'pyson': Sao.View.Form.PYSON, + 'reference': Sao.View.Form.Reference, + 'richtext': Sao.View.Form.RichText, + 'selection': Sao.View.Form.Selection, + 'sip': Sao.View.Form.SIP, + 'text': Sao.View.Form.Text, + 'time': Sao.View.Form.Time, + 'timedelta': Sao.View.Form.TimeDelta, + 'timestamp': Sao.View.Form.DateTime, + 'url': Sao.View.Form.URL, + }; }()); diff --git a/src/view/graph.js b/src/view/graph.js index e1bd9b7cc1..d31db47b19 100644 --- a/src/view/graph.js +++ b/src/view/graph.js @@ -3,77 +3,62 @@ (function() { 'use strict'; + Sao.View.GraphXMLViewParser = Sao.class_(Sao.View.XMLViewParser, { + init: function(view, exclude_field, fields) { + Sao.View.GraphXMLViewParser._super.init.call( + this, view, exclude_field, fields); + this._xfield = null; + this._yfields = []; + }, + _node_attributes: function(node) { + var node_attrs = {}; + for (var i = 0, len = node.attributes.length; i < len; i++) { + var attribute = node.attributes[i]; + node_attrs[attribute.name] = attribute.value; + } + if (node_attrs.name) { + if (!node_attrs.string && (node_attrs.name != '#')) { + var field = this.field_attrs[node_attrs.name]; + node_attrs.string = field.string; + } + } + return node_attrs; + }, + _parse_graph: function(node, attributes) { + [].forEach.call(node.childNodes, function(child) { + this.parse(child); + }.bind(this)); + var Widget = Sao.View.GraphXMLViewParser.WIDGETS[ + attributes.type || 'vbar']; + var widget = new Widget(this.view, this._xfield, this._yfields); + this.view.el.append(widget.el); + this.view.widgets.root = widget; + }, + _parse_x: function(node, attributes) { + for (var i = 0; i < node.children.length; i++) { + this._xfield = this._node_attributes(node.children[i]); + } + }, + _parse_y: function(node, attributes) { + for (var i = 0; i < node.children.length; i++) { + this._yfields.push(this._node_attributes(node.children[i])); + } + } + }); + Sao.View.Graph = Sao.class_(Sao.View, { - init: function(screen, xml) { - Sao.View.Graph._super.init.call(this, screen, xml); - this.view_type = 'graph'; + editable: false, + view_type: 'graph', + xml_parser: Sao.View.GraphXMLViewParser, + init: function(screen, xml, children_field) { this.el = jQuery('', { 'class': 'graph' }); - this.widgets = {}; - this.widget = this.parse(xml.children()[0]); - this.widgets.root = this.widget; - this.el.append(this.widget.el); - }, - parse: function(node) { - var field, xfield = null, yfields = [], yattrs; - var child, node_child; - var i, len, j, c_len; - var get_attributes = function(node) { - var attributes = {}, attribute; - for (var i = 0, len = node.attributes.length; i < len; i++) { - attribute = node.attributes[i]; - attributes[attribute.name] = attribute.value; - } - return attributes; - }; - - for (i=0, len=node.children.length; i < len; i++) { - child = node.children[i]; - switch (child.tagName) { - case 'x': - for (j=0, c_len=child.children.length; j < c_len; j++) { - xfield = get_attributes(child.children[j]); - field = this.screen.model.fields[xfield.name]; - xfield.type = field.description.type; - if (!(xfield.string || '')) { - xfield.string = field.description.string; - } - } - break; - case 'y': - for (j=0, c_len=child.children.length; j < c_len; j++) { - yattrs = get_attributes(child.children[j]); - if (!(yattrs.string || '') && - (yattrs.name != '#')) { - field = this.screen.model.fields[yattrs.name]; - yattrs.string = field.description.string; - } - yfields.push(yattrs); - } - break; - } - } - - var Widget; - switch (this.attributes.type) { - case 'hbar': - Widget = Sao.View.Graph.HorizontalBar; - break; - case 'line': - Widget = Sao.View.Graph.Line; - break; - case 'pie': - Widget = Sao.View.Graph.Pie; - break; - default: - Widget = Sao.View.Graph.VerticalBar; - } - return new Widget(this, xfield, yfields); + Sao.View.Graph._super.init.call(this, screen, xml); }, display: function() { - return this.widget.display(this.group); + return this.widgets.root.display(this.group); } }); @@ -337,4 +322,10 @@ } }); + Sao.View.GraphXMLViewParser.WIDGETS = { + 'hbar': Sao.View.Graph.HorizontalBar, + 'line': Sao.View.Graph.Line, + 'pie': Sao.View.Graph.Pie, + 'vbar': Sao.View.Graph.VerticalBar, + }; }()); diff --git a/src/view/tree.js b/src/view/tree.js index fef9febb80..53c05c0112 100644 --- a/src/view/tree.js +++ b/src/view/tree.js @@ -3,70 +3,91 @@ (function() { 'use strict'; - Sao.View.tree_column_get = function(type) { - switch (type) { - case 'char': - return Sao.View.Tree.CharColumn; - case 'text': - return Sao.View.Tree.TextColum; - case 'many2one': - return Sao.View.Tree.Many2OneColumn; - case 'one2one': - return Sao.View.Tree.One2OneColumn; - case 'date': - return Sao.View.Tree.DateColumn; - case 'time': - return Sao.View.Tree.TimeColumn; - case 'timedelta': - return Sao.View.Tree.TimeDeltaColumn; - case 'one2many': - return Sao.View.Tree.One2ManyColumn; - case 'many2many': - return Sao.View.Tree.Many2ManyColumn; - case 'selection': - return Sao.View.Tree.SelectionColumn; - case 'reference': - return Sao.View.Tree.ReferenceColumn; - case 'float': - case 'numeric': - return Sao.View.Tree.FloatColumn; - case 'integer': - case 'biginteger': - return Sao.View.Tree.IntegerColumn; - case 'boolean': - return Sao.View.Tree.BooleanColumn; - case 'binary': - return Sao.View.Tree.BinaryColumn; - case 'image': - return Sao.View.Tree.ImageColumn; - case 'url': - case 'email': - case 'callto': - case 'sip': - return Sao.View.Tree.URLColumn; - case 'progressbar': - return Sao.View.Tree.ProgressBar; + Sao.View.TreeXMLViewParser = Sao.class_(Sao.View.XMLViewParser, { + _parse_tree: function(node, attributes) { + [].forEach.call(node.childNodes, function(child) { + this.parse(child); + }.bind(this)); + }, + _parse_field: function(node, attributes) { + var name = attributes.name; + var ColumnFactory = Sao.View.TreeXMLViewParser.WIDGETS[ + attributes.widget]; + var column = new ColumnFactory(this.view.screen.model, attributes); + if (!this.view.widgets[name]) { + this.view.widgets[name] = []; + } + this.view.widgets[name].push(column); + + var prefixes = [], suffixes = []; + if (~['url', 'email', 'callto', 'sip' + ].indexOf(attributes.widget)) { + column.prefixes.push( + new Sao.View.Tree.Affix(attributes, attributes.widget)); + } + if ('icon' in attributes) { + column.prefixes.push(new Sao.View.Tree.Affix(attributes)); + } + var affix, affix_attributes; + var affixes = node.childNodes; + for (i = 0; i < affixes.length; i++) { + affix = affixes[i]; + affix_attributes = {}; + for (var i = 0, len = affix.attributes.length; i < len; i++) { + attribute = affix.attributes[i]; + affix_attributes[attribute.name] = attribute.value; + } + if (!affix_attributes.name) { + affix_attributes.name = name; + } + var list; + if (affix.tagName == 'prefix') { + list = column.prefixes; + } else { + list = column.suffixes; + } + list.push(new Sao.View.Tree.Affix(affix_attributes)); + } + if (!this.view.attributes.sequence && + !this.view.children_field && + this.field_attrs[name].sortable !== false){ + column.sortable = true; + } + this.view.columns.push(column); + + if (attributes.sum) { + var label = attributes.sum + Sao.i18n.gettext(': '); + var sum = jQuery('', { + 'text': label, + }); + var aggregate = jQuery('', { + 'class': 'value', + }); + this.view.sum_widgets[name] = [sum, aggregate]; + } + }, + _parse_button: function(node, attributes) { + var column = new Sao.View.Tree.ButtonColumn( + this.view.screen, attributes); + this.view.columns.push(column); } - }; + }); Sao.View.Tree = Sao.class_(Sao.View, { + view_type: 'tree', + xml_parser: Sao.View.TreeXMLViewParser, init: function(screen, xml, children_field) { - Sao.View.Tree._super.init.call(this, screen, xml); - this.view_type = 'tree'; + this.children_field = children_field; this.sum_widgets = {}; + this.columns = []; this.selection_mode = (screen.attributes.selection_mode || Sao.common.SELECTION_MULTIPLE); this.el = jQuery('', { 'class': 'treeview responsive' }); this.expanded = {}; - this.children_field = children_field; - this.editable = (Boolean(this.attributes.editable) && - !screen.attributes.readonly); - // Columns - this.columns = []; - this.create_columns(screen.model, xml); + Sao.View.Tree._super.init.call(this, screen, xml); // Table of records this.rows = []; @@ -164,100 +185,9 @@ this.display_size = Sao.config.display_size; }, - create_columns: function(model, xml) { - xml.find('tree').children().each(function(pos, child) { - var column, editable_column, attribute; - var attributes = {}; - for (var i = 0, len = child.attributes.length; i < len; i++) { - attribute = child.attributes[i]; - attributes[attribute.name] = attribute.value; - } - ['readonly', 'expand', 'completion'].forEach( - function(name) { - if (attributes[name]) { - attributes[name] = attributes[name] == 1; - } - }); - if (child.tagName == 'field') { - var name = attributes.name; - if (!attributes.widget) { - attributes.widget = model.fields[name].description.type; - } - var attribute_names = ['relation', 'domain', 'selection', - 'relation_field', 'string', 'views', 'invisible', - 'add_remove', 'sort', 'context', 'filename', - 'autocomplete', 'translate', 'create', 'delete', - 'selection_change_with', 'schema_model', 'required', - 'readonly', 'help']; - for (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]; - } - } - var ColumnFactory = Sao.View.tree_column_get( - attributes.widget); - column = new ColumnFactory(model, attributes); - - var prefixes = [], suffixes = []; - if (~['url', 'email', 'callto', 'sip' - ].indexOf(attributes.widget)) { - column.prefixes.push(new Sao.View.Tree.Affix( - attributes, attributes.widget)); - } - if ('icon' in attributes) { - column.prefixes.push(new Sao.View.Tree.Affix( - attributes)); - } - var affix, affix_attributes; - var affixes = child.childNodes; - for (i = 0; i < affixes.length; i++) { - affix = affixes[i]; - affix_attributes = {}; - for (i = 0, len = affix.attributes.length; i < len; - i++) { - attribute = affix.attributes[i]; - affix_attributes[attribute.name] = attribute.value; - } - if (!affix_attributes.name) { - affix_attributes.name = name; - } - if (affix.tagName == 'prefix') { - column.prefixes.push(new Sao.View.Tree.Affix( - affix_attributes)); - } else { - column.suffixes.push(new Sao.View.Tree.Affix( - affix_attributes)); - } - } - if (!this.attributes.sequence && - !this.children_field && - model.fields[name].description.sortable !== false){ - column.sortable = true; - } - this.fields[name] = true; - this.add_sum(attributes); - } else if (child.tagName == 'button') { - column = new Sao.View.Tree.ButtonColumn(this.screen, - attributes); - } - this.columns.push(column); - }.bind(this)); - }, - add_sum: function(attributes){ - if (!attributes.sum) { - return; - } - var label = attributes.sum + Sao.i18n.gettext(': '); - var sum = jQuery('', { - 'text': label, - }); - var aggregate = jQuery('', { - 'class': 'value', - }); - this.sum_widgets[attributes.name] = [sum, aggregate]; + get editable() { + return (Boolean(this.attributes.editable) && + !this.screen.attributes.readonly); }, sort_model: function(e){ var column = e.data; @@ -1395,12 +1325,11 @@ var state_attrs = col.field.get_state_attrs(this.record); var readonly = col.attributes.readonly || state_attrs.readonly; - if (!readonly) { - var EditableBuilder = Sao.View.editabletree_widget_get( - col.attributes.widget); - var widget = new EditableBuilder(col.attributes.name, - this.tree.screen.model, col.attributes); - widget.view = this.tree; + var EditableBuilder = Sao.View.EditableTree.WIDGETS[ + col.attributes.widget]; + if (!readonly && EditableBuilder) { + var widget = new EditableBuilder( + this.tree, col.attributes); widget.el.on('keydown', this.key_press.bind(this)); var editable_el = this.get_editable_el(td); @@ -2063,43 +1992,30 @@ } }); - Sao.View.editabletree_widget_get = function(type) { - switch (type) { - case 'char': - case 'text': - case 'url': - case 'email': - case 'callto': - case 'sip': - return Sao.View.EditableTree.Char; - case 'date': - return Sao.View.EditableTree.Date; - case 'time': - return Sao.View.EditableTree.Time; - case 'timedelta': - return Sao.View.EditableTree.TimeDelta; - case 'integer': - case 'biginteger': - return Sao.View.EditableTree.Integer; - case 'float': - case 'numeric': - return Sao.View.EditableTree.Float; - case 'selection': - return Sao.View.EditableTree.Selection; - case 'boolean': - return Sao.View.EditableTree.Boolean; - case 'many2one': - return Sao.View.EditableTree.Many2One; - case 'reference': - return Sao.View.EditableTree.Reference; - case 'one2one': - return Sao.View.EditableTree.One2One; - case 'one2many': - case 'many2many': - return Sao.View.EditableTree.One2Many; - case 'binary': - return Sao.View.EditableTree.Binary; - } + Sao.View.TreeXMLViewParser.WIDGETS = { + 'biginteger': Sao.View.Tree.IntegerColumn, + 'binary': Sao.View.Tree.BinaryColum, + 'boolean': Sao.View.Tree.BooleanColumn, + 'callto': Sao.View.Tree.URLColumn, + 'char': Sao.View.Tree.CharColumn, + 'date': Sao.View.Tree.DateColumn, + 'email': Sao.View.Tree.URLColumn, + 'float': Sao.View.Tree.FloatColumn, + 'image': Sao.View.Tree.ImageColumn, + 'integer': Sao.View.Tree.IntegerColumn, + 'many2many': Sao.View.Tree.Many2ManyColumn, + 'many2one': Sao.View.Tree.Many2OneColumn, + 'numeric': Sao.View.Tree.FloatColumn, + 'one2many': Sao.View.Tree.One2ManyColumn, + 'one2one': Sao.View.Tree.One2OneColumn, + 'progressbar': Sao.View.Tree.ProgressBar, + 'reference': Sao.View.Tree.ReferenceColumn, + 'selection': Sao.View.Tree.SelectionColumn, + 'sip': Sao.View.Tree.URLColumn, + 'text': Sao.View.Tree.TextColum, + 'time': Sao.View.Tree.TimeColumn, + 'timedelta': Sao.View.Tree.TimeDeltaColumn, + 'url': Sao.View.Tree.URLColumn, }; Sao.View.EditableTree = {}; @@ -2119,81 +2035,81 @@ Sao.View.EditableTree.Char = Sao.class_(Sao.View.Form.Char, { class_: 'editabletree-char', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Char._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Char._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); Sao.View.EditableTree.Date = Sao.class_(Sao.View.Form.Date, { class_: 'editabletree-date', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Date._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Date._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); Sao.View.EditableTree.Time = Sao.class_(Sao.View.Form.Time, { class_: 'editabletree-time', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Time._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Time._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); Sao.View.EditableTree.TimeDelta = Sao.class_(Sao.View.Form.TimeDelta, { class_: 'editabletree-timedelta', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.TimeDelta._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.TimeDelta._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); Sao.View.EditableTree.Integer = Sao.class_(Sao.View.Form.Integer, { class_: 'editabletree-integer', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Integer._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Integer._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); Sao.View.EditableTree.Float = Sao.class_(Sao.View.Form.Float, { class_: 'editabletree-float', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Float._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Float._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); Sao.View.EditableTree.Selection = Sao.class_(Sao.View.Form.Selection, { class_: 'editabletree-selection', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Selection._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Selection._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); Sao.View.EditableTree.Boolean = Sao.class_(Sao.View.Form.Boolean, { class_: 'editabletree-boolean', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Boolean._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Boolean._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); Sao.View.EditableTree.Many2One = Sao.class_(Sao.View.Form.Many2One, { class_: 'editabletree-many2one', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Many2One._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Many2One._super.init.call( + this, view, attributes); this.el.on('keydown', this.key_press.bind(this)); }, key_press: function(event_) { @@ -2208,9 +2124,9 @@ Sao.View.EditableTree.Reference = Sao.class_(Sao.View.Form.Reference, { class_: 'editabletree-reference', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Reference._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Reference._super.init.call( + this, view, attributes); this.el.on('keydown', this.key_press.bind(this)); }, key_press: function(event_) { @@ -2225,9 +2141,9 @@ Sao.View.EditableTree.One2One = Sao.class_(Sao.View.Form.One2One, { class_: 'editabletree-one2one', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.One2One._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.One2One._super.init.call( + this, view, attributes); this.el.on('keydown', this.key_press.bind(this)); }, key_press: function(event_) { @@ -2242,9 +2158,9 @@ Sao.View.EditableTree.One2Many = Sao.class_(Sao.View.EditableTree.Char, { class_: 'editabletree-one2many', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.One2Many._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.One2Many._super.init.call( + this, view, attributes); }, display: function(record, field) { if (record) { @@ -2264,11 +2180,35 @@ Sao.View.EditableTree.Binary = Sao.class_(Sao.View.Form.Binary, { class_: 'editabletree-binary', - init: function(field_name, model, attributes) { - Sao.View.EditableTree.Binary._super.init.call(this, field_name, - model, attributes); + init: function(view, attributes) { + Sao.View.EditableTree.Binary._super.init.call( + this, view, attributes); Sao.View.EditableTree.editable_mixin(this); } }); + Sao.View.EditableTree.WIDGETS = { + 'biginteger': Sao.View.EditableTree.Integer, + 'binary': Sao.View.EditableTree.Binary, + 'boolean': Sao.View.EditableTree.Boolean, + 'callto': Sao.View.EditableTree.Char, + 'char': Sao.View.EditableTree.Char, + 'date': Sao.View.EditableTree.Date, + 'email': Sao.View.EditableTree.Char, + 'float': Sao.View.EditableTree.Float, + 'integer': Sao.View.EditableTree.Integer, + 'many2many': Sao.View.EditableTree.Many2Many, + 'many2one': Sao.View.EditableTree.Many2One, + 'numeric': Sao.View.EditableTree.Float, + 'one2many': Sao.View.EditableTree.One2Many, + 'one2one': Sao.View.EditableTree.One2One, + 'reference': Sao.View.EditableTree.Reference, + 'selection': Sao.View.EditableTree.Selection, + 'sip': Sao.View.EditableTree.Char, + 'text': Sao.View.EditableTree.Char, + 'time': Sao.View.EditableTree.Time, + 'timedelta': Sao.View.EditableTree.TimeDelta, + 'url': Sao.View.EditableTree.Char, + }; + }());