Xavier (Open ERP) has proposed merging
lp:~openerp-dev/openerp-web/trunk-readonly-formview-xmo into lp:openerp-web.
Requested reviews:
Antony Lesuisse (OpenERP) (al-openerp)
Fabien Meghazi (OpenERP) (fme)
For more details, see:
https://code.launchpad.net/~openerp-dev/openerp-web/trunk-readonly-formview-xmo/+merge/76206
Readonly & repositionable forms:
~Cosmetics
==========
Moved the template name of the form widgets to the class (from the instance),
removed a bunch of now-redundant init methods.
Repositionable
==============
* Made widgets find their position in the rendered form template by looking up
a class, not an id (since an id "can't" be present twice in the same document,
and the widgets did a page-wise lookup which would always get their instance in
the first form render)
* Made the form view memoize its template (if on_loaded is called again without
any view data, the form just uses the previously computed template, of course
this blows up if there is no such thing)
* Added a method letting callers "move" the form to a different root $element
(caller still needs to call ``on_record_loaded`` afterwards to load a new
record in the new root, see "BunchaForms" in web_tests addon)
"Repositionable readonly" mode renders 50 forms in ~300ms on my machine.
Note: because the same form is used everywhere and most events work form-wise,
they're broken. I tried alleviating this by cloning the FormView (but keeping
the generated widgets tree and pre-rendered template), does not work as widgets
keep a reference to their FormView. This would be doable if it was possible to
clone/rebind the widgets tree to a new view, but that would also be far, far
more expensive (just cloning the TreeView and re-starting the widgets already
added ~30% to execution time on 50 forms)
Readonly
========
* Added a second form registry inheriting from the first one
* This registry contains read-only version of some form widgets
* If the form has been created but not started yet, swapping to readonly only
requires switching the registry on the form instance (see "BunchaForms" again)
* Otherwise need to cleanup some state, swap the registry and re-render the form
* Added a small switcher button, which just brute-forces the whole operation
--
https://code.launchpad.net/~openerp-dev/openerp-web/trunk-readonly-formview-xmo/+merge/76206
Your team OpenERP R&D Team is subscribed to branch
lp:~openerp-dev/openerp-web/trunk-readonly-formview-xmo.
=== modified file 'addons/web/static/src/js/view_form.js'
--- addons/web/static/src/js/view_form.js 2011-09-20 10:08:23 +0000
+++ addons/web/static/src/js/view_form.js 2011-09-20 12:43:33 +0000
@@ -73,16 +73,23 @@
w.stop();
});
},
+ reposition: function ($e) {
+ this.$element = $e;
+ this.on_loaded();
+ },
on_loaded: function(data) {
var self = this;
- this.fields_view = data;
- var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch);
+ if (data) {
+ this.fields_view = data;
+ var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch);
- this.$element.html(QWeb.render(this.form_template, { 'frame': frame, 'view': this }));
+ this.rendered = QWeb.render(this.form_template, { 'frame': frame, 'view': this });
+ }
+ this.$element.html(this.rendered);
_.each(this.widgets, function(w) {
w.start();
});
- this.$form_header = this.$element.find('#' + this.element_id + '_header');
+ this.$form_header = this.$element.find('.oe_form_header');
this.$form_header.find('div.oe_form_pager button[data-pager-action]').click(function() {
var action = $(this).data('pager-action');
self.on_pager_action(action);
@@ -93,6 +100,17 @@
this.$form_header.find('button.oe_form_button_cancel').click(this.do_cancel);
this.$form_header.find('button.oe_form_button_new').click(this.on_button_new);
this.$form_header.find('button.oe_form_button_duplicate').click(this.on_button_duplicate);
+ this.$form_header.find('button.oe_form_button_toggle').click(function () {
+ self.translatable_fields = [];
+ self.widgets = {};
+ self.fields = {};
+ self.$form_header.find('button').unbind('click');
+ self.registry = self.registry === openerp.web.form.widgets
+ ? openerp.web.form.readonly
+ : openerp.web.form.widgets;
+ self.on_loaded(self.fields_view);
+ self.reload();
+ });
if (this.options.sidebar && this.options.sidebar_id) {
this.sidebar = new openerp.web.Sidebar(this, this.options.sidebar_id);
@@ -196,7 +214,7 @@
}
},
do_update_pager: function(hide_index) {
- var $pager = this.$element.find('#' + this.element_id + '_header div.oe_form_pager');
+ var $pager = this.$form_header.find('div.oe_form_pager');
var index = hide_index ? '-' : this.dataset.index + 1;
$pager.find('span.oe_pager_index').html(index);
$pager.find('span.oe_pager_count').html(this.dataset.ids.length);
@@ -619,6 +637,7 @@
openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form.Widget# */{
template: 'Widget',
+ identifier_prefix: 'formview-widget-',
/**
* @constructs openerp.web.form.Widget
* @extends openerp.web.Widget
@@ -632,11 +651,13 @@
this.modifiers = JSON.parse(this.node.attrs.modifiers || '{}');
this.type = this.type || node.tag;
this.element_name = this.element_name || this.type;
- this.element_id = [this.view.element_id, this.element_name, this.view.widgets_counter++].join("_");
-
- this._super(view, this.element_id);
-
- this.view.widgets[this.element_id] = this;
+ this.element_class = [
+ 'formview', this.view.view_id, this.element_name,
+ this.view.widgets_counter++].join("_");
+
+ this._super(view);
+
+ this.view.widgets[this.element_class] = this;
this.children = node.children;
this.colspan = parseInt(node.attrs.colspan || 1, 10);
this.decrease_max_width = 0;
@@ -649,7 +670,7 @@
this.width = this.node.attrs.width;
},
start: function() {
- this.$element = $('#' + this.element_id);
+ this.$element = this.view.$element.find('.' + this.element_class);
},
stop: function() {
if (this.$element) {
@@ -758,13 +779,24 @@
for (var i = 0; i < node.children.length; i++) {
var n = node.children[i];
if (n.tag == "page") {
- var page = new openerp.web.form.WidgetNotebookPage(this.view, n, this, this.pages.length);
+ var page = new openerp.web.form.WidgetNotebookPage(
+ this.view, n, this, this.pages.length);
this.pages.push(page);
}
}
},
start: function() {
+ var self = this;
this._super.apply(this, arguments);
+ this.$element.find('> ul > li').each(function (index, tab_li) {
+ var page = self.pages[index],
+ id = _.uniqueId(self.element_name + '-');
+ page.element_id = id;
+ $(tab_li).find('a').attr('href', '#' + id);
+ });
+ this.$element.find('> div').each(function (index, page) {
+ page.id = self.pages[index].element_id;
+ });
this.$element.tabs();
this.view.on_button_new.add_last(this.do_select_first_visible_tab);
},
@@ -786,11 +818,11 @@
this.index = index;
this.element_name = 'page_' + index;
this._super(view, node);
- this.element_tab_id = this.element_id + '_tab';
},
start: function() {
this._super.apply(this, arguments);
- this.$element_tab = $('#' + this.element_tab_id);
+ this.$element_tab = this.notebook.$element.find(
+ '> ul > li:eq(' + this.index + ')');
},
update_dom: function() {
if (this.invisible && this.index === this.notebook.$element.tabs('option', 'selected')) {
@@ -802,9 +834,9 @@
});
openerp.web.form.WidgetSeparator = openerp.web.form.Widget.extend({
+ template: 'WidgetSeparator',
init: function(view, node) {
this._super(view, node);
- this.template = "WidgetSeparator";
this.orientation = node.attrs.orientation || 'horizontal';
if (this.orientation === 'vertical') {
this.width = '1';
@@ -814,9 +846,9 @@
});
openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({
+ template: 'WidgetButton',
init: function(view, node) {
this._super(view, node);
- this.template = "WidgetButton";
if (this.string) {
// We don't have button key bindings in the webclient
this.string = this.string.replace(/_/g, '');
@@ -838,7 +870,7 @@
});
} else {
if (this.node.attrs.confirm) {
- var dialog = $('<div>' + this.node.attrs.confirm + '</div>').dialog({
+ $('<div>' + this.node.attrs.confirm + '</div>').dialog({
title: 'Confirm',
modal: true,
buttons: {
@@ -867,6 +899,7 @@
});
openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({
+ template: 'WidgetLabel',
init: function(view, node) {
this.element_name = 'label_' + node.attrs.name;
@@ -877,7 +910,6 @@
this.template = "WidgetParagraph";
this.colspan = parseInt(this.node.attrs.colspan || 1, 10);
} else {
- this.template = "WidgetLabel";
this.colspan = 1;
this.width = '1%';
this.decrease_max_width = 1;
@@ -896,7 +928,7 @@
var self = this;
this.$element.find("label").dblclick(function() {
var widget = self['for'] || self;
- console.log(widget.element_id , widget);
+ console.log(widget.element_class , widget);
window.w = widget;
});
}
@@ -1035,10 +1067,7 @@
});
openerp.web.form.FieldChar = openerp.web.form.Field.extend({
- init: function(view, node) {
- this._super(view, node);
- this.template = "FieldChar";
- },
+ template: 'FieldChar',
start: function() {
this._super.apply(this, arguments);
this.$element.find('input').change(this.on_ui_change);
@@ -1047,6 +1076,7 @@
this._super.apply(this, arguments);
var show_value = openerp.web.format_value(value, this, '');
this.$element.find('input').val(show_value);
+ return show_value;
},
update_dom: function() {
this._super.apply(this, arguments);
@@ -1071,10 +1101,7 @@
});
openerp.web.form.FieldEmail = openerp.web.form.FieldChar.extend({
- init: function(view, node) {
- this._super(view, node);
- this.template = "FieldEmail";
- },
+ template: 'FieldEmail',
start: function() {
this._super.apply(this, arguments);
this.$element.find('button').click(this.on_button_clicked);
@@ -1085,18 +1112,11 @@
} else {
location.href = 'mailto:' + this.value;
}
- },
- set_value: function(value) {
- this._super.apply(this, arguments);
- this.$element.find('a').attr('href', 'mailto:' + this.$element.find('input').val());
}
});
openerp.web.form.FieldUrl = openerp.web.form.FieldChar.extend({
- init: function(view, node) {
- this._super(view, node);
- this.template = "FieldUrl";
- },
+ template: 'FieldUrl',
start: function() {
this._super.apply(this, arguments);
this.$element.find('button').click(this.on_button_clicked);
@@ -1122,9 +1142,9 @@
});
openerp.web.form.FieldDatetime = openerp.web.form.Field.extend({
+ template: 'FieldDate',
init: function(view, node) {
this._super(view, node);
- this.template = "FieldDate";
this.jqueryui_object = 'datetimepicker';
},
start: function() {
@@ -1215,10 +1235,7 @@
});
openerp.web.form.FieldText = openerp.web.form.Field.extend({
- init: function(view, node) {
- this._super(view, node);
- this.template = "FieldText";
- },
+ template: 'FieldText',
start: function() {
this._super.apply(this, arguments);
this.$element.find('textarea').change(this.on_ui_change);
@@ -1251,10 +1268,7 @@
});
openerp.web.form.FieldBoolean = openerp.web.form.Field.extend({
- init: function(view, node) {
- this._super(view, node);
- this.template = "FieldBoolean";
- },
+ template: 'FieldBoolean',
start: function() {
var self = this;
this._super.apply(this, arguments);
@@ -1285,10 +1299,7 @@
});
openerp.web.form.FieldProgressBar = openerp.web.form.Field.extend({
- init: function(view, node) {
- this._super(view, node);
- this.template = "FieldProgressBar";
- },
+ template: 'FieldProgressBar',
start: function() {
this._super.apply(this, arguments);
this.$element.find('div').progressbar({
@@ -1311,10 +1322,10 @@
});
openerp.web.form.FieldSelection = openerp.web.form.Field.extend({
+ template: 'FieldSelection',
init: function(view, node) {
var self = this;
this._super(view, node);
- this.template = "FieldSelection";
this.values = this.field.selection;
_.each(this.values, function(v, i) {
if (v[0] === false && v[1] === '') {
@@ -1421,9 +1432,9 @@
};
openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({
+ template: 'FieldMany2One',
init: function(view, node) {
this._super(view, node);
- this.template = "FieldMany2One";
this.limit = 7;
this.value = null;
this.cm_id = _.uniqueId('m2o_cm_');
@@ -1748,10 +1759,10 @@
}
};
openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
+ template: 'FieldOne2Many',
multi_selection: false,
init: function(view, node) {
this._super(view, node);
- this.template = "FieldOne2Many";
this.is_started = $.Deferred();
this.form_last_update = $.Deferred();
this.disable_utility_classes = true;
@@ -1932,9 +1943,8 @@
},
validate: function() {
this.invalid = false;
- var self = this;
- var view = self.viewmanager.views[self.viewmanager.active_view].controller;
- if (self.viewmanager.active_view === "form") {
+ var view = this.viewmanager.views[this.viewmanager.active_view].controller;
+ if (this.viewmanager.active_view === "form") {
for (var f in view.fields) {
f = view.fields[f];
if (!f.is_valid()) {
@@ -2007,10 +2017,10 @@
});
openerp.web.form.FieldMany2Many = openerp.web.form.Field.extend({
+ template: 'FieldMany2Many',
multi_selection: false,
init: function(view, node) {
this._super(view, node);
- this.template = "FieldMany2Many";
this.list_id = _.uniqueId("many2many");
this.is_started = $.Deferred();
},
@@ -2352,9 +2362,9 @@
});
openerp.web.form.FieldReference = openerp.web.form.Field.extend({
+ template: 'FieldReference',
init: function(view, node) {
this._super(view, node);
- this.template = "FieldReference";
this.fields_view = {
fields: {
selection: {
@@ -2489,10 +2499,7 @@
});
openerp.web.form.FieldBinaryFile = openerp.web.form.FieldBinary.extend({
- init: function(view, node) {
- this._super(view, node);
- this.template = "FieldBinaryFile";
- },
+ template: 'FieldBinaryFile',
set_value: function(value) {
this._super.apply(this, arguments);
var show_value = (value != null && value !== false) ? value : '';
@@ -2520,10 +2527,7 @@
});
openerp.web.form.FieldBinaryImage = openerp.web.form.FieldBinary.extend({
- init: function(view, node) {
- this._super(view, node);
- this.template = "FieldBinaryImage";
- },
+ template: 'FieldBinaryImage',
start: function() {
this._super.apply(this, arguments);
this.$image = this.$element.find('img.oe-binary-image');
@@ -2598,6 +2602,93 @@
}
});
+openerp.web.form.WidgetNotebookReadonly = openerp.web.form.WidgetNotebook.extend({
+ template: 'WidgetNotebook.readonly'
+});
+openerp.web.form.FieldReadonly = openerp.web.form.Field.extend({
+
+});
+openerp.web.form.FieldCharReadonly = openerp.web.form.FieldReadonly.extend({
+ template: 'FieldChar.readonly',
+ set_value: function (value) {
+ this._super.apply(this, arguments);
+ var show_value = openerp.web.format_value(value, this, '');
+ this.$element.find('div').text(show_value);
+ return show_value;
+ }
+});
+openerp.web.form.FieldURIReadonly = openerp.web.form.FieldCharReadonly.extend({
+ template: 'FieldURI.readonly',
+ scheme: null,
+ set_value: function (value) {
+ var displayed = this._super.apply(this, arguments);
+ this.$element.find('a')
+ .attr('href', this.scheme + ':' + displayed)
+ .text(displayed);
+ }
+});
+openerp.web.form.FieldEmailReadonly = openerp.web.form.FieldURIReadonly.extend({
+ scheme: 'mailto'
+});
+openerp.web.form.FieldUrlReadonly = openerp.web.form.FieldURIReadonly.extend({
+ set_value: function (value) {
+ var s = /(\w+):(\.+)/.match(value);
+ if (!(s[0] === 'http' || s[0] === 'https')) { return; }
+ this.scheme = s[0];
+ this._super(s[1]);
+ }
+});
+openerp.web.form.FieldBooleanReadonly = openerp.web.form.FieldCharReadonly.extend({
+ set_value: function (value) {
+ this._super(value ? '\u2714' : '\u2718');
+ }
+});
+openerp.web.form.FieldSelectionReadonly = openerp.web.form.FieldReadonly.extend({
+ template: 'FieldChar.readonly',
+ init: function(view, node) {
+ // lifted straight from r/w version
+ var self = this;
+ this._super(view, node);
+ this.values = this.field.selection;
+ _.each(this.values, function(v, i) {
+ if (v[0] === false && v[1] === '') {
+ self.values.splice(i, 1);
+ }
+ });
+ this.values.unshift([false, '']);
+ },
+ set_value: function (value) {
+ value = value === null ? false : value;
+ value = value instanceof Array ? value[0] : value;
+ var option = _(this.values)
+ .detect(function (record) { return record[0] === value; });
+ this._super(value);
+ this.$element.find('div').text(option ? option[1] : this.values[0][1]);
+ }
+});
+openerp.web.form.FieldMany2OneReadonly = openerp.web.form.FieldCharReadonly.extend({
+ set_value: function (value) {
+ value = value || null;
+ this.invalid = false;
+ var self = this;
+ this.tmp_value = value;
+ self.update_dom();
+ self.on_value_changed();
+ var real_set_value = function(rval) {
+ self.$element.find('div').text(rval ? rval[1] : '');
+ };
+ if(typeof(value) === "number") {
+ var dataset = new openerp.web.DataSetStatic(
+ this, this.field.relation, self.build_context());
+ dataset.name_get([value], function(data) {
+ real_set_value(data[0]);
+ }).fail(function() {self.tmp_value = undefined;});
+ } else {
+ setTimeout(function() {real_set_value(value);}, 0);
+ }
+ }
+});
+
/**
* Registry of form widgets, called by :js:`openerp.web.FormView`
*/
@@ -2630,6 +2721,22 @@
'binary': 'openerp.web.form.FieldBinaryFile',
'statusbar': 'openerp.web.form.FieldStatus'
});
+openerp.web.form.readonly = openerp.web.form.widgets.clone({
+ 'notebook': 'openerp.web.form.WidgetNotebookReadonly',
+ 'char': 'openerp.web.form.FieldCharReadonly',
+ 'email': 'openerp.web.form.FieldEmailReadonly',
+ 'url': 'openerp.web.form.FieldUrlReadonly',
+ 'text': 'openerp.web.form.FieldCharReadonly',
+ 'text_wiki' : 'openerp.web.form.FieldCharReadonly',
+ 'date': 'openerp.web.form.FieldCharReadonly',
+ 'datetime': 'openerp.web.form.FieldCharReadonly',
+ 'selection' : 'openerp.web.form.FieldSelectionReadonly',
+ 'many2one': 'openerp.web.form.FieldMany2OneReadonly',
+ 'boolean': 'openerp.web.form.FieldBooleanReadonly',
+ 'float': 'openerp.web.form.FieldCharReadonly',
+ 'integer': 'openerp.web.form.FieldCharReadonly',
+ 'float_time': 'openerp.web.form.FieldCharReadonly'
+});
};
=== modified file 'addons/web/static/src/xml/base.xml'
--- addons/web/static/src/xml/base.xml 2011-09-19 11:57:35 +0000
+++ addons/web/static/src/xml/base.xml 2011-09-20 12:43:33 +0000
@@ -639,7 +639,7 @@
<t t-raw="frame.render()"/>
</t>
<t t-name="FormView">
- <div class="oe_form_header" t-att-id="view.element_id + '_header'">
+ <div class="oe_form_header">
<div class="oe_form_buttons" t-if="view.options.action_buttons !== false">
<!--<button type="button" class="oe_form_button_save">
<span class="oe_form_on_update">Save</span>
@@ -652,6 +652,7 @@
<!--<button type="button" class="oe_form_button_cancel">Cancel</button>-->
<button type="button" class="oe_form_button_new">New</button>
<button type="button" class="oe_form_button_duplicate oe_form_on_update">Duplicate</button>
+ <button type="button" class="oe_form_button_toggle">Readonly/Editable</button>
</div>
<div class="oe_form_pager" t-if="view.options.pager !== false">
<button type="button" data-pager-action="first">First</button>
@@ -711,8 +712,7 @@
t-att-width="td.width"
t-att-nowrap="td.nowrap or td.is_field_m2o? 'true' : undefined"
t-att-valign="td.table ? 'top' : undefined"
- t-att-id="td.element_id"
- t-attf-class="oe_form_frame_cell #{td.classname}"
+ t-attf-class="oe_form_frame_cell #{td.classname} #{td.element_class}"
>
<t t-raw="td.render()"/>
</td>
@@ -722,8 +722,8 @@
</t>
<t t-name="WidgetNotebook">
<ul>
- <li t-foreach="widget.pages" t-as="page" t-att-id="page.element_tab_id">
- <a t-att-href="'#' + page.element_id">
+ <li t-foreach="widget.pages" t-as="page">
+ <a href="#">
<t t-esc="page.string"/>
</a>
</li>
@@ -733,17 +733,23 @@
</t>
</t>
<t t-name="WidgetNotebookPage">
- <div t-att-id="widget.element_id">
+ <div>
<t t-call="WidgetFrame"/>
</div>
</t>
+<t t-name="WidgetNotebook.readonly">
+ <t t-foreach="widget.pages" t-as="page">
+ <h3><t t-esc="page.string"/></h3>
+ <t t-raw="page.render()"/>
+ </t>
+</t>
<t t-name="WidgetSeparator">
<div t-if="widget.orientation !== 'vertical'" t-att-class="'separator ' + widget.orientation">
<t t-esc="widget.string"/>
</div>
</t>
<t t-name="WidgetLabel">
- <label t-att-for="widget.element_id + '_field'"
+ <label t-att-for="widget.element_id"
t-att-class="'oe_label' + (widget.help ? '_help' : '')"
t-att-title="widget.help">
<t t-esc="widget.string"/>
@@ -757,12 +763,22 @@
<t t-name="FieldChar">
<input type="text" size="1"
t-att-name="widget.name"
- t-att-id="widget.element_id + '_field'"
- t-att-class="'field_' + widget.type"
+ t-att-id="widget.element_id"
+ t-attf-class="field_#{widget.type} #{widget.element_class}"
t-attf-style="width: #{widget.field.translate ? '99' : '100'}%"
/>
<img class="oe_field_translate" t-if="widget.field.translate" src="/web/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/>
</t>
+<t t-name="FieldChar.readonly">
+ <div
+ t-att-id="widget.element_id"
+ t-attf-class="field_#{widget.type} #{widget.element_class}"
+ t-attf-style="width: #{widget.field.translate ? '99' : '100'}%">
+ </div>
+</t>
+<t t-name="FieldURI.readonly">
+ <a href="#">#</a>
+</t>
<t t-name="FieldEmail">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
@@ -794,17 +810,19 @@
<t t-name="FieldText">
<textarea rows="6"
t-att-name="widget.name"
- t-att-id="widget.element_id + '_field'"
- t-att-class="'field_' + widget.type"
+ t-att-id="widget.element_id"
+ t-attf-class="field_#{widget.type} #{widget.element_class}"
t-attf-style="width: #{widget.field.translate ? '99' : '100'}%"
></textarea>
<img class="oe_field_translate" t-if="widget.field.translate" src="/web/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/>
</t>
<t t-name="FieldDate">
<t t-call="FieldChar"/>
- <img class="oe_input_icon oe_datepicker_trigger" src="/web/static/src/img/ui/field_calendar.png"
+ <img
+ class="oe_input_icon oe_datepicker_trigger" src="/web/static/src/img/ui/field_calendar.png"
title="Select date" width="16" height="16" border="0"/>
- <div class="oe_datepicker ui-widget-content ui-corner-all" style="display: none; position: absolute; z-index: 1;">
+ <div
+ class="oe_datepicker ui-widget-content ui-corner-all" style="display: none; position: absolute; z-index: 1;">
<div class="oe_datepicker_container"/>
<button type="button" class="oe_datepicker_close ui-state-default ui-priority-primary ui-corner-all" style="float: right;">Done</button>
</div>
@@ -813,7 +831,7 @@
<select
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
- t-att-class="'field_' + widget.type"
+ t-attf-class="field_#{widget.type} #{widget.element_class}"
style="width: 100%">
<t t-foreach="widget.values" t-as="option">
<option><t t-esc="option[1]"/></option>
@@ -821,9 +839,9 @@
</select>
</t>
<t t-name="FieldMany2One">
- <div t-att-id="widget.element_id" class="oe-m2o">
- <input t-att-id="widget.element_id + '_input'" type="text" size="1" style="width: 100%;"/>
- <span class="oe-m2o-drop-down-button" t-att-id="widget.element_id + '_drop_down'">
+ <div t-att-class="widget.element_class" class="oe-m2o">
+ <input type="text" size="1" style="width: 100%;"/>
+ <span class="oe-m2o-drop-down-button">
<img src="/web/static/src/img/down-arrow.png" /></span>
<span class="oe-m2o-cm-button" t-att-id="widget.name + '_open'">
<img src="/web/static/src/img/icons/gtk-index.png"/></span>
@@ -846,8 +864,6 @@
</ul>
</t>
<t t-name="FieldOne2Many">
- <div t-att-id="widget.element_id">
- </div>
</t>
<t t-name="FieldMany2Many">
<div t-att-id="widget.list_id"></div>
@@ -855,10 +871,10 @@
<t t-name="FieldReference">
<table border="0" width="100%" cellpadding="0" cellspacing="0" class="oe_frame oe_forms">
<tr>
- <td t-att-id="widget.selection.element_id" class="oe_form_frame_cell oe_form_selection">
+ <td t-attf-class="oe_form_frame_cell oe_form_selection #{widget.selection.element_class}">
<t t-raw="widget.selection.render()"/>
</td>
- <td t-att-id="widget.m2o.element_id" class="oe_form_frame_cell oe_form_many2one" nowrap="true">
+ <td class="oe_form_frame_cell oe_form_many2one #{widget.selection.element_class}" nowrap="true">
<t t-raw="widget.m2o.render()"/>
</td>
</tr>
@@ -868,7 +884,7 @@
<input type="checkbox"
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
- t-att-class="'field_' + widget.type"/>
+ t-attf-class="field_#{widget.type} #{widget.element_class}"/>
</t>
<t t-name="FieldProgressBar">
<div t-opentag="true" class="oe-progressbar">
@@ -883,7 +899,7 @@
t-att-border="widget.readonly ? 0 : 1"
t-att-id="widget.element_id + '_field'"
t-att-name="widget.name"
- t-att-class="'field_' + widget.type"
+ t-attf-class="field_#{widget.type} #{widget.element_class}"
t-att-width="widget.node.attrs.img_width || widget.node.attrs.width"
t-att-height="widget.node.attrs.img_height || widget.node.attrs.height"
/>
@@ -931,7 +947,7 @@
<input type="text" size="1"
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
- t-att-class="'field_' + widget.type" style="width: 100%"
+ t-attf-class="field_#{widget.type} #{widget.element_class}" style="width: 100%"
/>
</td>
<td class="oe-binary" nowrap="true">
@@ -976,7 +992,7 @@
</t>
<t t-name="WidgetButton">
<button type="button"
- t-att-id="widget.element_id + '_button'"
+ t-attf-class="#{widget.element_class}"
t-att-title="widget.help"
style="width: 100%" class="button">
<img t-if="widget.node.attrs.icon" t-att-src="'/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
=== added directory 'addons/web_tests'
=== added file 'addons/web_tests/__init__.py'
--- addons/web_tests/__init__.py 1970-01-01 00:00:00 +0000
+++ addons/web_tests/__init__.py 2011-09-20 12:43:33 +0000
@@ -0,0 +1,1 @@
+# -*- coding: utf-8 -*-
=== added file 'addons/web_tests/__openerp__.py'
--- addons/web_tests/__openerp__.py 1970-01-01 00:00:00 +0000
+++ addons/web_tests/__openerp__.py 2011-09-20 12:43:33 +0000
@@ -0,0 +1,8 @@
+{
+ "name": "Tests",
+ "version": "2.0",
+ "depends": [],
+ "js": ["static/src/js/*.js"],
+ "css": ['static/src/css/*.css'],
+ 'active': True,
+}
=== added directory 'addons/web_tests/static'
=== added directory 'addons/web_tests/static/src'
=== added directory 'addons/web_tests/static/src/css'
=== added file 'addons/web_tests/static/src/css/web_tests.css'
--- addons/web_tests/static/src/css/web_tests.css 1970-01-01 00:00:00 +0000
+++ addons/web_tests/static/src/css/web_tests.css 2011-09-20 12:43:33 +0000
@@ -0,0 +1,3 @@
+.oe-bunchaforms > div {
+ float: left;
+}
=== added directory 'addons/web_tests/static/src/js'
=== added file 'addons/web_tests/static/src/js/web_tests.js'
--- addons/web_tests/static/src/js/web_tests.js 1970-01-01 00:00:00 +0000
+++ addons/web_tests/static/src/js/web_tests.js 2011-09-20 12:43:33 +0000
@@ -0,0 +1,37 @@
+openerp.web_tests = function (db) {
+ db.web.client_actions.add(
+ 'buncha-forms', 'instance.web_tests.BunchaForms');
+ db.web_tests = {};
+ db.web_tests.BunchaForms = db.web.Widget.extend({
+ init: function (parent) {
+ this._super(parent);
+ this.dataset = new db.web.DataSetSearch(this, 'test.listview.relations');
+ this.form = new db.web.FormView(this, this.dataset, false, {
+ action_buttons: false,
+ pager: false
+ });
+ this.form.registry = db.web.form.readonly;
+ },
+ render: function () {
+ return '<div class="oe-bunchaforms"></div>';
+ },
+ start: function () {
+ $.when(
+ this.dataset.read_slice(),
+ this.form.appendTo(this.$element)).then(this.on_everything_loaded);
+ },
+ on_everything_loaded: function (slice) {
+ var records = slice[0].records;
+ if (!records.length) {
+ this.form.on_record_loaded({});
+ return;
+ }
+ this.form.on_record_loaded(records[0]);
+ _(records.slice(1)).each(function (record, index) {
+ this.dataset.index = index+1;
+ this.form.reposition($('<div>').appendTo(this.$element));
+ this.form.on_record_loaded(record);
+ }, this);
+ }
+ });
+};
=== modified file 'openerp-web.py'
--- openerp-web.py 2011-09-16 13:18:44 +0000
+++ openerp-web.py 2011-09-20 12:43:33 +0000
@@ -38,7 +38,7 @@
optparser.add_option("--log-config", dest="log_config",
default='', help="Log config file", metavar="LOG_CONFIG")
optparser.add_option('--multi-threaded', dest='threaded',
- default=False, action='store_true',
+ default=True, action='store_true',
help="Use multiple threads to handle requests")
import web.common.dispatch
_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help : https://help.launchpad.net/ListHelp