From 0fee0cea0079a57d362a5752cf3499a28c58bc43 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 08:45:23 +0200 Subject: [PATCH 001/222] [ADD] backbone-ification of Widgets API bzr revid: xmo@openerp.com-20120611064523-gczdqmfes5f1g9kj --- addons/web/static/src/js/corelib.js | 177 ++++++++++++++++++++++------ 1 file changed, 143 insertions(+), 34 deletions(-) diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 94c748f839c..8455a183f87 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -238,6 +238,20 @@ instance.web.ParentedMixin = { } }; +/** + * Utility function for APIs which can take either a value or a function which + * returns a value + * + * @param {Object} object + * @param {String} property + * @returns {Object} + */ +var getValue = function (object, property) { + if (object == null) { return null; } + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; +}; + /** * Backbone's events. Do not ever use it directly, use EventDispatcherMixin instead. * @@ -490,23 +504,19 @@ instance.web.CallbackEnabledMixin = _.extend({}, instance.web.PropertiesMixin, { * * The semantics of this precisely replace closing over the method call. * - * @param {String} method_name name of the method to invoke + * @param {String|Function} method function or name of the method to invoke * @returns {Function} proxied method */ - proxy: function (method_name) { + proxy: function (method) { var self = this; return function () { - return self[method_name].apply(self, arguments); + var fn = (method instanceof String) ? self[method] : method; + return fn.apply(self, arguments); } } }); instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { - /** - * Tag name when creating a default $element. - * @type string - */ - tagName: 'div', /** * Constructs the widget and sets its parent if a parent is given. * @@ -516,14 +526,9 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { * @param {instance.web.Widget} parent Binds the current instance to the given Widget instance. * When that widget is destroyed by calling destroy(), the current instance will be * destroyed too. Can be null. - * @param {String} element_id Deprecated. Sets the element_id. Only useful when you want - * to bind the current Widget to an already existing part of the DOM, which is not compatible - * with the DOM insertion methods provided by the current implementation of Widget. So - * for new components this argument should not be provided any more. */ init: function(parent) { instance.web.CallbackEnabledMixin.init.call(this); - this.$element = $(document.createElement(this.tagName)); this.setParent(parent); }, /** @@ -533,8 +538,8 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { _.each(this.getChildren(), function(el) { el.destroy(); }); - if(this.$element != null) { - this.$element.remove(); + if(this.$el) { + this.$el.remove(); } instance.web.PropertiesMixin.destroy.call(this); }, @@ -546,7 +551,7 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { appendTo: function(target) { var self = this; return this.__widgetRenderAndInsert(function(t) { - self.$element.appendTo(t); + self.$el.appendTo(t); }, target); }, /** @@ -557,7 +562,7 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { prependTo: function(target) { var self = this; return this.__widgetRenderAndInsert(function(t) { - self.$element.prependTo(t); + self.$el.prependTo(t); }, target); }, /** @@ -568,7 +573,7 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { insertAfter: function(target) { var self = this; return this.__widgetRenderAndInsert(function(t) { - self.$element.insertAfter(t); + self.$el.insertAfter(t); }, target); }, /** @@ -579,7 +584,7 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { insertBefore: function(target) { var self = this; return this.__widgetRenderAndInsert(function(t) { - self.$element.insertBefore(t); + self.$el.insertBefore(t); }, target); }, /** @@ -589,7 +594,7 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { */ replace: function(target) { return this.__widgetRenderAndInsert(_.bind(function(t) { - this.$element.replaceAll(t); + this.$el.replaceAll(t); }, this), target); }, __widgetRenderAndInsert: function(insertion, target) { @@ -612,6 +617,7 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, { * @returns {jQuery.Deferred} */ start: function() { + return $.when(); } }); @@ -688,12 +694,9 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { * @param {instance.web.Widget} parent Binds the current instance to the given Widget instance. * When that widget is destroyed by calling destroy(), the current instance will be * destroyed too. Can be null. - * @param {String} element_id Deprecated. Sets the element_id. Only useful when you want - * to bind the current Widget to an already existing part of the DOM, which is not compatible - * with the DOM insertion methods provided by the current implementation of Widget. So - * for new components this argument should not be provided any more. */ init: function(parent) { + this._uid = _.uniqueId('-widget-'); instance.web.WidgetMixin.init.call(this,parent); this.session = instance.connection; }, @@ -703,20 +706,126 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { * key that references `this`. */ renderElement: function() { - var rendered = null; - if (this.template) - rendered = instance.web.qweb.render(this.template, {widget: this}); - if (_.str.trim(rendered)) { - var elem = $(rendered); - this.$element.replaceWith(elem); - this.$element = elem; + var $el; + if (this.template) { + $el = $(_.str.trim(instance.web.qweb.render( + this.template, {widget: this}))); + } else { + var attrs = _.extend({}, getValue(this, 'attributes') || {}); + if (this.id) { attrs.id = this.id; } + if (this.className) { attrs['class'] = this.className; } + $el = $(this.make(this.tagName, attrs)) + } + this.setElement($el); + }, + + /** + * Re-sets the widget's root element (el/$el/$element). + * + * Includes: + * * re-delegating events + * * re-binding sub-elements + * * if the widget already had a root element, replacing the pre-existing + * element in the DOM + * + * @param {HTMLElement | jQuery} element new root element for the widget + * @return {*} + */ + setElement: function (element) { + if (this.$el) { + this.undelegateEvents(); + this.unbindElements(); + this.$el.replaceWith(element); + } + + this.$element = this.$el = (element instanceof $) ? element : $(element); + this.el = this.$el[0]; + + this.bindElements(); + this.delegateEvents(); + + return this; + }, + + // Backbone-ish API + tagName: 'div', + id: null, + className: null, + attributes: {}, + /** + * Utility function to build small DOM elements. + * + * @param {String} tagName name of the DOM element to create + * @param {Object} [attributes] map of DOM attributes to set on the element + * @param {String} [content] HTML content to set on the element + * @return {Element} + */ + make: function (tagName, attributes, content) { + var el = document.createElement(tagName); + if (attributes) { + $(el).attrs(attributes); + } + if (content) { + $(el).html(content); + } + return el; + }, + events: {}, + delegateEvents: function () { + var events = getValue(this, 'events'); + if (_.isEmpty(events)) { return; } + + for(var key in events) { + if (!events.hasOwnProperty(key)) { continue; } + + var method = this.proxy(events[key]); + + var match = /^(\S+)(\s+(.*))?$/.exec(key); + var event = match[1]; + var selector = match[3]; + + // add namespace for easy un-delegation + event += '.delegated-events' + this._uid; + if (!selector) { + this.$el.on(event, method); + } else { + this.$el.on(event, selector, method); + } + } + }, + undelegateEvents: function () { + this.$el.off('.delegated-events' + this._uid); + }, + elements: {}, + bindElements: function () { + var elements = getValue(this, 'elements'); + if (_.isEmpty(elements)) { return; } + + for (var selector in elements) { + if (!elements.hasOwnProperty(selector)) { continue; } + + // TODO: ensure at least one element matched? + this[elements[selector]] = this.$(selector); + } + }, + unbindElements: function () { + var elements = getValue(this, 'elements'); + if (_.isEmpty(elements)) { return; } + + for (var selector in elements) { + if (!elements.hasOwnProperty(selector)) { continue; } + + delete this[elements[selector]]; } }, /** - * Shortcut for $element.find() like backbone + * Shortcut for ``this.$el.find(selector)`` + * + * @param {String} selector CSS selector, rooted in $el + * @returns {jQuery} selector match */ - "$": function() { - return this.$element.find.apply(this.$element,arguments); + $: function(selector) { + return this.$el.find(selector); }, /** * Informs the action manager to do an action. This supposes that From 459eb54d77f8fce5cce460d56c74121fe8125275 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 10:50:19 +0200 Subject: [PATCH 002/222] [FIX] broken unit tests bzr revid: xmo@openerp.com-20120611085019-z16aggfnuovgh1p4 --- addons/web/static/src/xml/base.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 3764395dc13..7bbc1884beb 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1409,10 +1409,10 @@ -
+
-
+

M Custom Filters

    From 26ec50e0603561128a5470f871d9ea487ed95560 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 11:18:03 +0200 Subject: [PATCH 003/222] [FIX] bug in new 'proxy' implementation revealed by searchview tests bzr revid: xmo@openerp.com-20120611091803-kzo5j5t8p82gwr6i --- addons/web/static/src/js/corelib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 8455a183f87..61464a58930 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -510,7 +510,7 @@ instance.web.CallbackEnabledMixin = _.extend({}, instance.web.PropertiesMixin, { proxy: function (method) { var self = this; return function () { - var fn = (method instanceof String) ? self[method] : method; + var fn = (typeof method === 'string') ? self[method] : method; return fn.apply(self, arguments); } } From 5c701e2b1d8070e49f0dc247f1b649f19ebc7751 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 11:18:20 +0200 Subject: [PATCH 004/222] [FIX] behavior of OldWidget for new Widget implementation bzr revid: xmo@openerp.com-20120611091820-m5gm67psqeh1xxx8 --- addons/web/static/src/js/coresetup.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/js/coresetup.js b/addons/web/static/src/js/coresetup.js index 4defde54a3c..d419c7ac3c1 100644 --- a/addons/web/static/src/js/coresetup.js +++ b/addons/web/static/src/js/coresetup.js @@ -19,15 +19,15 @@ instance.web.OldWidget = instance.web.Widget.extend({ this._super(parent); this.element_id = element_id; this.element_id = this.element_id || _.uniqueId('widget-'); + var tmp = document.getElementById(this.element_id); - this.$element = tmp ? $(tmp) : $(document.createElement(this.tagName)); + this.setElement(tmp || this.make(this.tagName)); }, renderElement: function() { var rendered = this.render(); if (rendered) { - var elem = $(rendered); - this.$element.replaceWith(elem); - this.$element = elem; + var $el = $(rendered); + this.setElement($el); } return this; }, From 3f1757869c51cadb87d57abbb0392c78cb888bda Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 11:18:57 +0200 Subject: [PATCH 005/222] [IMP] make searchview base widget not inherit from OldWidget anymore bzr revid: xmo@openerp.com-20120611091857-wcpc2oqywoc0gg51 --- addons/web/static/src/js/search.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 85521a14651..22649197317 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -886,13 +886,13 @@ instance.web.search.Invalid = instance.web.Class.extend( /** @lends instance.web ); } }); -instance.web.search.Widget = instance.web.OldWidget.extend( /** @lends instance.web.search.Widget# */{ +instance.web.search.Widget = instance.web.Widget.extend( /** @lends instance.web.search.Widget# */{ template: null, /** * Root class of all search widgets * * @constructs instance.web.search.Widget - * @extends instance.web.OldWidget + * @extends instance.web.Widget * * @param view the ancestor view of this widget */ From 772bed66f33f16886ac0211cda6bd34ba05e4e3d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 11:48:40 +0200 Subject: [PATCH 006/222] [TEST] Widget#proxy, with both String and Function arguments bzr revid: xmo@openerp.com-20120611094840-mtilgirzwlhkl2qc --- addons/web/static/test/Widget.js | 67 ++++++++++++++++++++++++++++++++ addons/web/static/test/test.html | 1 + 2 files changed, 68 insertions(+) create mode 100644 addons/web/static/test/Widget.js diff --git a/addons/web/static/test/Widget.js b/addons/web/static/test/Widget.js new file mode 100644 index 00000000000..dc86e99b38a --- /dev/null +++ b/addons/web/static/test/Widget.js @@ -0,0 +1,67 @@ +$(document).ready(function () { + var $fix = $('#qunit-fixture'); + var mod = { + setup: function () { + instance = window.openerp.init([]); + window.openerp.web.corelib(instance); + } + }; + var instance; + + module('Widget.proxy', mod); + test('(String)', function () { + var W = instance.web.Widget.extend({ + exec: function () { + this.executed = true; + } + }); + var w = new W; + var fn = w.proxy('exec'); + fn(); + ok(w.executed, 'should execute the named method in the right context'); + }); + test('(String)(*args)', function () { + var W = instance.web.Widget.extend({ + exec: function (arg) { + this.executed = arg; + } + }); + var w = new W; + var fn = w.proxy('exec'); + fn(42); + ok(w.executed, "should execute the named method in the right context"); + equal(w.executed, 42, "should be passed the proxy's arguments"); + }); + test('(String), include', function () { + // the proxy function should handle methods being changed on the class + // and should always proxy "by name", to the most recent one + var W = instance.web.Widget.extend({ + exec: function () { + this.executed = 1; + } + }); + var w = new W; + var fn = w.proxy('exec'); + W.include({ + exec: function () { this.executed = 2; } + }); + + fn(); + equal(w.executed, 2, "should be lazily resolved"); + }); + + test('(Function)', function () { + var w = new (instance.web.Widget.extend({ })); + + var fn = w.proxy(function () { this.executed = true; }); + fn(); + ok(w.executed, "should set the function's context (like Function#bind)"); + }); + test('(Function)(*args)', function () { + var w = new (instance.web.Widget.extend({ })); + + var fn = w.proxy(function (arg) { this.executed = arg; }); + fn(42); + equal(w.executed, 42, "should be passed the proxy's arguments"); + }); +}); diff --git a/addons/web/static/test/test.html b/addons/web/static/test/test.html index e352f63c17c..dd0d08a4986 100644 --- a/addons/web/static/test/test.html +++ b/addons/web/static/test/test.html @@ -55,4 +55,5 @@ + From a0c5057dbacef8e8f1841245c58ad4f52da57ef9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 13:32:38 +0200 Subject: [PATCH 007/222] [TEST] Widget#renderElement with no template specified, fix Widget#make's handling of attributes bzr revid: xmo@openerp.com-20120611113238-wz516g9tl0xp1igd --- addons/web/static/src/js/corelib.js | 4 +- addons/web/static/test/Widget.js | 68 +++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 61464a58930..83586ec57d4 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -762,8 +762,8 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { */ make: function (tagName, attributes, content) { var el = document.createElement(tagName); - if (attributes) { - $(el).attrs(attributes); + if (!_.isEmpty(attributes)) { + $(el).attr(attributes); } if (content) { $(el).html(content); diff --git a/addons/web/static/test/Widget.js b/addons/web/static/test/Widget.js index dc86e99b38a..51a5182845d 100644 --- a/addons/web/static/test/Widget.js +++ b/addons/web/static/test/Widget.js @@ -64,4 +64,72 @@ $(document).ready(function () { fn(42); equal(w.executed, 42, "should be passed the proxy's arguments"); }); + + module('Widget.renderElement', mod); + test('no template, default', function () { + var w = new (instance.web.Widget.extend({ })); + + ok(!w.$el, "should not initially have a root element"); + w.renderElement(); + ok(w.$el, "should have generated a root element"); + strictEqual(w.$element, w.$el, "should provide $element alias"); + ok(w.$el.is(w.el), "should provide raw DOM alias"); + + equal(w.el.nodeName, 'DIV', "should have generated the default element"); + equal(w.el.attributes.length, 0, "should not have generated any attribute"); + ok(_.isEmpty(w.$el.html(), "should not have generated any content")); + }); + test('no template, custom tag', function () { + var w = new (instance.web.Widget.extend({ + tagName: 'ul' + })); + w.renderElement(); + + equal(w.el.nodeName, 'UL', "should have generated the custom element tag"); + }); + test('no template, @id', function () { + var w = new (instance.web.Widget.extend({ + id: 'foo' + })); + w.renderElement(); + + equal(w.el.attributes.length, 1, "should have one attribute"); + equal(w.$el.attr('id'), 'foo', "should have generated the id attribute"); + equal(w.el.id, 'foo', "should also be available via property"); + }); + test('no template, @className', function () { + var w = new (instance.web.Widget.extend({ + className: 'oe_some_class' + })); + w.renderElement(); + + equal(w.el.className, 'oe_some_class', "should have the right property"); + equal(w.$el.attr('class'), 'oe_some_class', "should have the right attribute"); + }); + test('no template, bunch of attributes', function () { + var w = new (instance.web.Widget.extend({ + attributes: { + 'id': 'some_id', + 'class': 'some_class', + 'data-foo': 'data attribute', + 'clark': 'gable', + 'spoiler': 'snape kills dumbledore' + } + })); + w.renderElement(); + + equal(w.el.attributes.length, 5, "should have all the specified attributes"); + + equal(w.el.id, 'some_id'); + equal(w.$el.attr('id'), 'some_id'); + + equal(w.el.className, 'some_class'); + equal(w.$el.attr('class'), 'some_class'); + + equal(w.$el.attr('data-foo'), 'data attribute'); + equal(w.$el.data('foo'), 'data attribute'); + + equal(w.$el.attr('clark'), 'gable'); + equal(w.$el.attr('spoiler'), 'snape kills dumbledore'); + }); }); From c531cb96ca2b0dc74ec6f9569eec8ea24c6506a1 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 13:48:49 +0200 Subject: [PATCH 008/222] [TEST] Wisget#renderElement with template bzr revid: xmo@openerp.com-20120611114849-dwk4erae5f1tyc6o --- addons/web/static/test/Widget.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/addons/web/static/test/Widget.js b/addons/web/static/test/Widget.js index 51a5182845d..3a2301e53f8 100644 --- a/addons/web/static/test/Widget.js +++ b/addons/web/static/test/Widget.js @@ -132,4 +132,24 @@ $(document).ready(function () { equal(w.$el.attr('clark'), 'gable'); equal(w.$el.attr('spoiler'), 'snape kills dumbledore'); }); + + test('template', function () { + instance.web.qweb = new QWeb2.Engine(); + instance.web.qweb.add_template('' + + '
      ' + + '
    1. ' + + '' + + '
    2. ' + + '
    ' + + '
    '); + + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template' + })); + w.renderElement(); + + equal(w.el.nodeName, 'OL'); + equal(w.$el.children().length, 5); + equal(w.el.textContent, '01234'); + }); }); From 2a9bd73a83c27e3dfab7e7b6438ad9988930ae39 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 14:08:18 +0200 Subject: [PATCH 009/222] [TEST] Widget#$ shortcut bzr revid: xmo@openerp.com-20120611120818-apsawz6kypnpc5m3 --- addons/web/static/test/Widget.js | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/addons/web/static/test/Widget.js b/addons/web/static/test/Widget.js index 3a2301e53f8..f588d9a258c 100644 --- a/addons/web/static/test/Widget.js +++ b/addons/web/static/test/Widget.js @@ -4,6 +4,15 @@ $(document).ready(function () { setup: function () { instance = window.openerp.init([]); window.openerp.web.corelib(instance); + + instance.web.qweb = new QWeb2.Engine(); + instance.web.qweb.add_template('' + + '
      ' + + '
    1. ' + + '' + + '
    2. ' + + '
    ' + + '
    '); } }; var instance; @@ -134,15 +143,6 @@ $(document).ready(function () { }); test('template', function () { - instance.web.qweb = new QWeb2.Engine(); - instance.web.qweb.add_template('' + - '
      ' + - '
    1. ' + - '' + - '
    2. ' + - '
    ' + - '
    '); - var w = new (instance.web.Widget.extend({ template: 'test.widget.template' })); @@ -152,4 +152,15 @@ $(document).ready(function () { equal(w.$el.children().length, 5); equal(w.el.textContent, '01234'); }); + + module('Widget.$', mod); + test('basic-alias', function () { + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template' + })); + w.renderElement(); + + ok(w.$('li:eq(3)').is(w.$el.find('li:eq(3)')), + "should do the same thing as calling find on the widget root"); + }); }); From c64d8859a01933a89cd5c06df4324d7e11081a4f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 14:48:24 +0200 Subject: [PATCH 010/222] [TEST] declarative events delegation bzr revid: xmo@openerp.com-20120611124824-w83h6betknrajyte --- addons/web/static/test/Widget.js | 49 +++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/addons/web/static/test/Widget.js b/addons/web/static/test/Widget.js index f588d9a258c..d797120a341 100644 --- a/addons/web/static/test/Widget.js +++ b/addons/web/static/test/Widget.js @@ -8,7 +8,9 @@ $(document).ready(function () { instance.web.qweb = new QWeb2.Engine(); instance.web.qweb.add_template('' + '
      ' + - '
    1. ' + + '
    2. ' + + '' + '' + '
    3. ' + '
    ' + @@ -163,4 +165,49 @@ $(document).ready(function () { ok(w.$('li:eq(3)').is(w.$el.find('li:eq(3)')), "should do the same thing as calling find on the widget root"); }); + + module('Widget.events', mod); + test('delegate', function () { + var a = []; + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template', + events: { + 'click': function () { + a[0] = true; + strictEqual(this, w, "should trigger events in widget") + }, + 'click li.class-3': 'class3', + 'change input': function () { a[2] = true; } + }, + class3: function () { a[1] = true; } + })); + w.renderElement(); + + w.$el.click(); + w.$('li:eq(3)').click(); + w.$('input:last').val('foo').change(); + + for(var i=0; i<3; ++i) { + ok(a[i], "should pass test " + i); + } + }); + test('undelegate', function () { + var clicked = false, newclicked = false; + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template', + events: { 'click li': function () { clicked = true; } } + })); + w.renderElement(); + w.$el.on('click', 'li', function () { newclicked = true }); + + w.$('li').click(); + ok(clicked, "should trigger bound events"); + ok(newclicked, "should trigger bound events"); + clicked = newclicked = false; + + w.undelegateEvents(); + w.$('li').click(); + ok(!clicked, "undelegate should unbind events delegated"); + ok(newclicked, "undelegate should only unbind events it created"); + }); }); From b19354ae2005e83980a938c8e534fe55b5d1c14e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 14:54:54 +0200 Subject: [PATCH 011/222] [TEST] getValue/events as a callable bzr revid: xmo@openerp.com-20120611125454-nli5gkds9ffksmdm --- addons/web/static/test/Widget.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/addons/web/static/test/Widget.js b/addons/web/static/test/Widget.js index d797120a341..36d6795ff7c 100644 --- a/addons/web/static/test/Widget.js +++ b/addons/web/static/test/Widget.js @@ -191,6 +191,17 @@ $(document).ready(function () { ok(a[i], "should pass test " + i); } }); + test('delegate(Function)', function () { + var clicked = false, fn = function () { + return { 'click li': function () { clicked = true; } }; }; + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template', + events: fn + })); + w.renderElement(); + w.$('li:first').click(); + ok(clicked, "should accept #events to be a function"); + }); test('undelegate', function () { var clicked = false, newclicked = false; var w = new (instance.web.Widget.extend({ From d6f376464516709c7b4ad7631ac1e49e4e39fe5e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 16:41:08 +0200 Subject: [PATCH 012/222] [REM] declarative elements binding, not sure there's much point and can add later bzr revid: xmo@openerp.com-20120611144108-pw8pz5p06prsikxe --- addons/web/static/src/js/corelib.js | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 83586ec57d4..e9fd4e1fedf 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -734,14 +734,12 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { setElement: function (element) { if (this.$el) { this.undelegateEvents(); - this.unbindElements(); this.$el.replaceWith(element); } this.$element = this.$el = (element instanceof $) ? element : $(element); this.el = this.$el[0]; - this.bindElements(); this.delegateEvents(); return this; @@ -796,28 +794,6 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { undelegateEvents: function () { this.$el.off('.delegated-events' + this._uid); }, - elements: {}, - bindElements: function () { - var elements = getValue(this, 'elements'); - if (_.isEmpty(elements)) { return; } - - for (var selector in elements) { - if (!elements.hasOwnProperty(selector)) { continue; } - - // TODO: ensure at least one element matched? - this[elements[selector]] = this.$(selector); - } - }, - unbindElements: function () { - var elements = getValue(this, 'elements'); - if (_.isEmpty(elements)) { return; } - - for (var selector in elements) { - if (!elements.hasOwnProperty(selector)) { continue; } - - delete this[elements[selector]]; - } - }, /** * Shortcut for ``this.$el.find(selector)`` * From d2f7ddb43eeb53973e7957fa9bccf3153d7f7bc5 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 11 Jun 2012 17:07:02 +0200 Subject: [PATCH 013/222] [ADD] doc for backbone-ish APIs bzr revid: xmo@openerp.com-20120611150702-r4c9kyxmu8m7g4c0 --- doc/addons.rst | 109 -------------------- doc/index.rst | 1 + doc/widget.rst | 270 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 271 insertions(+), 109 deletions(-) create mode 100644 doc/widget.rst diff --git a/doc/addons.rst b/doc/addons.rst index da1f1f28769..35878b04430 100644 --- a/doc/addons.rst +++ b/doc/addons.rst @@ -113,103 +113,6 @@ initializing the addon. Creating new standard roles --------------------------- -Widget -++++++ - -This is the base class for all visual components. It provides a number of -services for the management of a DOM subtree: - -* Rendering with QWeb - -* Parenting-child relations - -* Life-cycle management (including facilitating children destruction when a - parent object is removed) - -* DOM insertion, via jQuery-powered insertion methods. Insertion targets can - be anything the corresponding jQuery method accepts (generally selectors, - DOM nodes and jQuery objects): - - :js:func:`~openerp.base.Widget.appendTo` - Renders the widget and inserts it as the last child of the target, uses - `.appendTo()`_ - - :js:func:`~openerp.base.Widget.prependTo` - Renders the widget and inserts it as the first child of the target, uses - `.prependTo()`_ - - :js:func:`~openerp.base.Widget.insertAfter` - Renders the widget and inserts it as the preceding sibling of the target, - uses `.insertAfter()`_ - - :js:func:`~openerp.base.Widget.insertBefore` - Renders the widget and inserts it as the following sibling of the target, - uses `.insertBefore()`_ - -:js:class:`~openerp.base.Widget` inherits from -:js:class:`~openerp.base.SessionAware`, so subclasses can easily access the -RPC layers. - -Subclassing Widget -~~~~~~~~~~~~~~~~~~ - -:js:class:`~openerp.base.Widget` is subclassed in the standard manner (via the -:js:func:`~openerp.base.Class.extend` method), and provides a number of -abstract properties and concrete methods (which you may or may not want to -override). Creating a subclass looks like this: - -.. code-block:: javascript - - var MyWidget = openerp.base.Widget.extend({ - // QWeb template to use when rendering the object - template: "MyQWebTemplate", - - init: function(parent) { - this._super(parent); - // insert code to execute before rendering, for object - // initialization - }, - start: function() { - this._super(); - // post-rendering initialization code, at this point - // ``this.$element`` has been initialized - this.$element.find(".my_button").click(/* an example of event binding * /); - - // if ``start`` is asynchronous, return a promise object so callers - // know when the object is done initializing - return this.rpc(/* … */) - } - }); - -The new class can then be used in the following manner: - -.. code-block:: javascript - - // Create the instance - var my_widget = new MyWidget(this); - // Render and insert into DOM - my_widget.appendTo(".some-div"); - -After these two lines have executed (and any promise returned by ``appendTo`` -has been resolved if needed), the widget is ready to be used. - -.. note:: the insertion methods will start the widget themselves, and will - return the result of :js:func:`~openerp.base.Widget.start()`. - - If for some reason you do not want to call these methods, you will - have to first call :js:func:`~openerp.base.Widget.render()` on the - widget, then insert it into your DOM and start it. - -If the widget is not needed anymore (because it's transient), simply terminate -it: - -.. code-block:: javascript - - my_widget.stop(); - -will unbind all DOM events, remove the widget's content from the DOM and -destroy all widget data. - Views +++++ @@ -541,18 +444,6 @@ Python .. _promise object: http://api.jquery.com/deferred.promise/ -.. _.appendTo(): - http://api.jquery.com/appendTo/ - -.. _.prependTo(): - http://api.jquery.com/prependTo/ - -.. _.insertAfter(): - http://api.jquery.com/insertAfter/ - -.. _.insertBefore(): - http://api.jquery.com/insertBefore/ - .. _Rosetta: .. _Launchpad's own translation tool: https://help.launchpad.net/Translations diff --git a/doc/index.rst b/doc/index.rst index 9f54b879acc..1f660426a88 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -16,6 +16,7 @@ Contents: async rpc + widget search-view Older stuff diff --git a/doc/widget.rst b/doc/widget.rst new file mode 100644 index 00000000000..9868e4030e0 --- /dev/null +++ b/doc/widget.rst @@ -0,0 +1,270 @@ +User Interaction: Widget +======================== + +This is the base class for all visual components. It corresponds to an MVC +view. It provides a number of services to handle a section of a page: + +* Rendering with QWeb + +* Parenting-child relations + +* Life-cycle management (including facilitating children destruction when a + parent object is removed) + +* DOM insertion, via jQuery-powered insertion methods. Insertion targets can + be anything the corresponding jQuery method accepts (generally selectors, + DOM nodes and jQuery objects): + + :js:func:`~openerp.base.Widget.appendTo` + Renders the widget and inserts it as the last child of the target, uses + `.appendTo()`_ + + :js:func:`~openerp.base.Widget.prependTo` + Renders the widget and inserts it as the first child of the target, uses + `.prependTo()`_ + + :js:func:`~openerp.base.Widget.insertAfter` + Renders the widget and inserts it as the preceding sibling of the target, + uses `.insertAfter()`_ + + :js:func:`~openerp.base.Widget.insertBefore` + Renders the widget and inserts it as the following sibling of the target, + uses `.insertBefore()`_ + +* Backbone-compatible shortcuts + +DOM Root +-------- + +A :js:class:`~openerp.web.Widget` is responsible for a section of the +page materialized by the DOM root of the widget. The DOM root is +available via the :js:attr:`~openerp.web.Widget.el` and +:js:attr:`~openerp.web.Widget.$el` attributes, which are respectively +the raw DOM Element and the jQuery wrapper around the DOM element. + +.. note:: + + both attributes are compatible with Backbone's equivalent, there + is also the :js:attr:`~openerp.web.Widget.$element` attribute + which aliases to :js:attr:`~openerp.web.Widget.$el` and remains + for backwards compatiblity reasons. + +There are two main ways to define and generate this DOM root: + +.. js:attribute:: openerp.web.Widget.template + + Should be set to the name of a QWeb template (a + :js:class:`String`). If set, the template will be rendered after + the widget has been initialized but before it has been + started. The root element generated by the template will be set as + the DOM root of the widget. + +.. js:attribute:: openerp.web.Widget.tagName + + Used if the widget has no template defined. Defaults to ``div``, + will be used as the tag name to create the DOM element to set as + the widget's DOM root. It is possible to further customize this + generated DOM root with the following attributes: + + .. js:attribute:: openerp.web.Widget.id + + Used to generate an ``id`` attribute on the generated DOM + root. + + .. js:attribute:: openerp.web.Widget.className + + Used to generate a ``class`` attribute on the generated DOM root. + + .. js:attribute:: openerp.web.Widget.attributes + + Mapping (object literal) of attribute names to attribute + values. Each of these k:v pairs will be set as a DOM attribute + on the generated DOM root. + + None of these is used in case a template is specified on the widget. + +The DOM root can also be defined programmatically by overridding + +.. js:function:: openerp.web.Widget.renderElement + + Renders the widget's DOM root and sets it. The default + implementation will render a set template or generate an element + as described above, and will call + :js:func:`~openerp.web.Widget.setElement` on the result. + + Any override to :js:func:`~openerp.web.Widget.renderElement` which + does not call its ``_super`` **must** call + :js:func:`~openerp.web.Widget.setElement` with whatever it + generated or the widget's behavior is undefined. + +Accessing DOM content +~~~~~~~~~~~~~~~~~~~~~ + +Because a widget is only responsible for the content below its DOM +root, there is a shortcut for selecting sub-sections of a widget's +DOM: + +.. js:function:: openerp.web.Widget.$(selector) + + Applies the CSS selector specified as parameter to the widget's + DOM root. + + .. code-block:: javascript + + this.$(selector); + + is functionally identical to: + + .. code-block:: javascript + + this.$element.find(selector); + + :param String selector: CSS selector + :returns: jQuery object + + .. note:: this helper method is compatible with + ``Backbone.View.$`` + +Resetting the DOM root +~~~~~~~~~~~~~~~~~~~~~~ + +.. js:function:: openerp.web.Widget.setElement(element) + + Re-sets the widget's DOM root to the provided element, also + handles re-setting the various aliases of the DOM root as well as + unsetting and re-setting delegated events. + + :param Element element: a DOM element or jQuery object to set as + the widget's DOM root + + .. note:: should be mostly compatible with `Backbone's + setElement`_ + +DOM events handling +------------------- + +A widget will generally need to respond to user action within its +section of the page. This entails binding events to DOM elements. + +To this end, :js:class:`~openerp.web.Widget` provides an shortcut: + +.. js:attribute:: openerp.web.Widget.events + + Events are a mapping of ``event selector`` (an event name and a + CSS selector separated by a space) to a callback. The callback can + be either a method name in the widget or a function. In either + case, the ``this`` will be set to the widget. + + The selector is used for jQuery's `event delegation`_, the + callback will only be triggered for descendants of the DOM root + matching the selector [0]_. If the selector is left out (only an + event name is specified), the event will be set directly on the + widget's DOM root. + +.. js:function:: openerp.web.Widget.delegateEvents + + This method is in charge of binding + :js:attr:`~openerp.web.Widget.events` to the DOM. It is + automatically called after setting the widget's DOM root. + + It can be overridden to set up more complex events than the + :js:attr:`~openerp.web.Widget.events` map allows, but the parent + should always be called (or :js:attr:`~openerp.web.Widget.events` + won't be handled correctly). + +.. js:function:: openerp.web.Widget.undelegateEvents + + This method is in charge of unbinding + :js:attr:`~openerp.web.Widget.events` from the DOM root when the + widget is destroyed or the DOM root is reset, in order to avoid + leaving "phantom" events. + + It should be overridden to un-set any event set in an override of + :js:func:`~openerp.web.Widget.delegateEvents`. + +.. note:: this behavior should be compatible with `Backbone's + delegateEvents`_, apart from not accepting any argument. + +Subclassing Widget +------------------ + +:js:class:`~openerp.base.Widget` is subclassed in the standard manner (via the +:js:func:`~openerp.base.Class.extend` method), and provides a number of +abstract properties and concrete methods (which you may or may not want to +override). Creating a subclass looks like this: + +.. code-block:: javascript + + var MyWidget = openerp.base.Widget.extend({ + // QWeb template to use when rendering the object + template: "MyQWebTemplate", + + init: function(parent) { + this._super(parent); + // insert code to execute before rendering, for object + // initialization + }, + start: function() { + this._super(); + // post-rendering initialization code, at this point + // ``this.$element`` has been initialized + this.$element.find(".my_button").click(/* an example of event binding * /); + + // if ``start`` is asynchronous, return a promise object so callers + // know when the object is done initializing + return this.rpc(/* … */) + } + }); + +The new class can then be used in the following manner: + +.. code-block:: javascript + + // Create the instance + var my_widget = new MyWidget(this); + // Render and insert into DOM + my_widget.appendTo(".some-div"); + +After these two lines have executed (and any promise returned by ``appendTo`` +has been resolved if needed), the widget is ready to be used. + +.. note:: the insertion methods will start the widget themselves, and will + return the result of :js:func:`~openerp.base.Widget.start()`. + + If for some reason you do not want to call these methods, you will + have to first call :js:func:`~openerp.base.Widget.render()` on the + widget, then insert it into your DOM and start it. + +If the widget is not needed anymore (because it's transient), simply terminate +it: + +.. code-block:: javascript + + my_widget.destroy(); + +will unbind all DOM events, remove the widget's content from the DOM and +destroy all widget data. + +.. [0] not all DOM events are compatible with events delegation + +.. _.appendTo(): + http://api.jquery.com/appendTo/ + +.. _.prependTo(): + http://api.jquery.com/prependTo/ + +.. _.insertAfter(): + http://api.jquery.com/insertAfter/ + +.. _.insertBefore(): + http://api.jquery.com/insertBefore/ + +.. _event delegation: + http://api.jquery.com/delegate/ + +.. _Backbone's setElement: + http://backbonejs.org/#View-setElement + +.. _Backbone's delegateEvents: + http://backbonejs.org/#View-delegateEvents + From f0ad5fedacc2e994ef8ba45b05113278ac72db95 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 12 Jun 2012 15:21:20 +0200 Subject: [PATCH 014/222] [IMP] move .replaceWith() back into renderElement * Better formalizes repeated calls to renderElement * Makes setElement cleaner and less surprising to call bzr revid: xmo@openerp.com-20120612132120-egsg4kr5n2riv4zk --- addons/web/static/src/js/corelib.js | 5 +++- addons/web/static/test/Widget.js | 42 ++++++++++++++++++++++------- doc/widget.rst | 12 ++++++++- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index e9fd4e1fedf..73fa6839607 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -716,7 +716,11 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { if (this.className) { attrs['class'] = this.className; } $el = $(this.make(this.tagName, attrs)) } + var $oldel = this.$el; this.setElement($el); + if ($oldel && !$oldel.is(this.$el)) { + $oldel.replaceWith(this.$el); + } }, /** @@ -734,7 +738,6 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { setElement: function (element) { if (this.$el) { this.undelegateEvents(); - this.$el.replaceWith(element); } this.$element = this.$el = (element instanceof $) ? element : $(element); diff --git a/addons/web/static/test/Widget.js b/addons/web/static/test/Widget.js index 36d6795ff7c..b50dd233a13 100644 --- a/addons/web/static/test/Widget.js +++ b/addons/web/static/test/Widget.js @@ -6,15 +6,21 @@ $(document).ready(function () { window.openerp.web.corelib(instance); instance.web.qweb = new QWeb2.Engine(); - instance.web.qweb.add_template('' + - '
      ' + - '
    1. ' + - '' + - '' + - '
    2. ' + - '
    ' + - '
    '); + instance.web.qweb.add_template( + '' + + '' + + '
      ' + + '
    1. ' + + '' + + '' + + '
    2. ' + + '
    ' + + '
    ' + + '' + + '

    ' + + '
    ' + + '
    '); } }; var instance; @@ -221,4 +227,22 @@ $(document).ready(function () { ok(!clicked, "undelegate should unbind events delegated"); ok(newclicked, "undelegate should only unbind events it created"); }); + + module('Widget.renderElement', mod); + test('repeated', function () { + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template-value' + })); + w.value = 42; + w.appendTo($fix) + .always(start) + .done(function () { + equal($fix.find('p').text(), '42', "DOM fixture should contain initial value"); + equal(w.$el.text(), '42', "should set initial value"); + w.value = 36; + w.renderElement(); + equal($fix.find('p').text(), '36', "DOM fixture should use new value"); + equal(w.$el.text(), '36', "should set new value"); + }); + }); }); diff --git a/doc/widget.rst b/doc/widget.rst index 9868e4030e0..b29260c5882 100644 --- a/doc/widget.rst +++ b/doc/widget.rst @@ -95,7 +95,17 @@ The DOM root can also be defined programmatically by overridding Any override to :js:func:`~openerp.web.Widget.renderElement` which does not call its ``_super`` **must** call :js:func:`~openerp.web.Widget.setElement` with whatever it - generated or the widget's behavior is undefined. + generated or the widget's behavior is undefined.r + + .. note:: + + The default :js:func:`~openerp.web.Widget.renderElement` can + be called repeatedly, it will *replace* the previous DOM root + (using ``replaceWith``). However, this requires that the + widget correctly sets and unsets its events (and children + widgets). Generally, + :js:func:`~openerp.web.Widget.renderElement` should not be + called repeatedly unless the widget advertizes this feature. Accessing DOM content ~~~~~~~~~~~~~~~~~~~~~ From 43fb6b3ee39999fd55a045a961372691b8926e58 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 11 Jul 2012 17:25:58 +0200 Subject: [PATCH 015/222] [CHG] require that Widget#attributes be an object if present, not a function bzr revid: xmo@openerp.com-20120711152558-9jm096g7mowgfvf5 --- addons/web/static/src/js/corelib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/corelib.js b/addons/web/static/src/js/corelib.js index 73fa6839607..d71ff91247d 100644 --- a/addons/web/static/src/js/corelib.js +++ b/addons/web/static/src/js/corelib.js @@ -711,10 +711,10 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, { $el = $(_.str.trim(instance.web.qweb.render( this.template, {widget: this}))); } else { - var attrs = _.extend({}, getValue(this, 'attributes') || {}); + var attrs = _.extend({}, this.attributes || {}); if (this.id) { attrs.id = this.id; } if (this.className) { attrs['class'] = this.className; } - $el = $(this.make(this.tagName, attrs)) + $el = $(this.make(this.tagName, attrs)); } var $oldel = this.$el; this.setElement($el); From 8895562fffc7a409d4b3c054a6f418cde67b9c98 Mon Sep 17 00:00:00 2001 From: "Foram Katharotiya (OpenERP)" Date: Tue, 17 Jul 2012 17:03:04 +0530 Subject: [PATCH 016/222] [IMP] improve layout of sales config wizard bzr revid: fka@tinyerp.com-20120717113304-0mg50z82ia2qznq6 --- addons/base_setup/res_config_view.xml | 24 ++-- addons/crm/res_config_view.xml | 55 +++++++--- addons/crm_claim/res_config_view.xml | 12 +- addons/plugin_outlook/plugin_outlook.xml | 12 +- .../plugin_thunderbird/plugin_thunderbird.xml | 14 +-- addons/sale/res_config_view.xml | 103 +++++++++++++----- 6 files changed, 149 insertions(+), 71 deletions(-) diff --git a/addons/base_setup/res_config_view.xml b/addons/base_setup/res_config_view.xml index 5227b0885a9..c3ebab6da4e 100644 --- a/addons/base_setup/res_config_view.xml +++ b/addons/base_setup/res_config_view.xml @@ -30,7 +30,6 @@
- + + - - - - - - - - - + + + + + + Sales Application + sale.config.settings + form + + +
+
+
+
+
+
+
+
+
+
diff --git a/addons/crm_claim/res_config_view.xml b/addons/crm_claim/res_config_view.xml index 327bf144544..bdcec2df43c 100644 --- a/addons/crm_claim/res_config_view.xml +++ b/addons/crm_claim/res_config_view.xml @@ -9,14 +9,12 @@ - - diff --git a/addons/plugin_outlook/plugin_outlook.xml b/addons/plugin_outlook/plugin_outlook.xml index 0340a7c502f..428c7f2a649 100644 --- a/addons/plugin_outlook/plugin_outlook.xml +++ b/addons/plugin_outlook/plugin_outlook.xml @@ -52,14 +52,12 @@ form - - diff --git a/addons/plugin_thunderbird/plugin_thunderbird.xml b/addons/plugin_thunderbird/plugin_thunderbird.xml index fef7772dfdf..5be79c069ff 100644 --- a/addons/plugin_thunderbird/plugin_thunderbird.xml +++ b/addons/plugin_thunderbird/plugin_thunderbird.xml @@ -58,14 +58,12 @@ form - - +
+
+
+
diff --git a/addons/sale/res_config_view.xml b/addons/sale/res_config_view.xml index 74796bac6fc..8bead1c4411 100644 --- a/addons/sale/res_config_view.xml +++ b/addons/sale/res_config_view.xml @@ -8,34 +8,85 @@ form - + +
+ + + + + +
+ - - - - - - - - - - - -
- - - - - - - - - - - - + + + + + + + + +
Use contract to be able to manage your services with multiple invoicing as part of the same contract with your customer
+ +
From f4aca67e14492bc88eec7a4312c8df2243356d73 Mon Sep 17 00:00:00 2001 From: "Foram Katharotiya (OpenERP)" Date: Tue, 17 Jul 2012 19:00:24 +0530 Subject: [PATCH 017/222] [IMP] improve label of fields in sales config wizard bzr revid: fka@tinyerp.com-20120717133024-7ah0r5cx5p12r3bj --- addons/base_setup/res_config_view.xml | 8 ++-- addons/crm/res_config_view.xml | 14 +++--- addons/crm_claim/res_config_view.xml | 2 +- addons/plugin_outlook/plugin_outlook.xml | 2 +- .../plugin_thunderbird/plugin_thunderbird.xml | 2 +- addons/sale/res_config_view.xml | 43 ++++++++++--------- 6 files changed, 36 insertions(+), 35 deletions(-) diff --git a/addons/base_setup/res_config_view.xml b/addons/base_setup/res_config_view.xml index c3ebab6da4e..2cd55d0cdc8 100644 --- a/addons/base_setup/res_config_view.xml +++ b/addons/base_setup/res_config_view.xml @@ -63,10 +63,10 @@ Users can do it from the mail client by pressing a button or it can be configured to automatically synchronize from your mail server.
diff --git a/addons/crm/res_config_view.xml b/addons/crm/res_config_view.xml index dc6a8c7d94d..de5260072b7 100644 --- a/addons/crm/res_config_view.xml +++ b/addons/crm/res_config_view.xml @@ -13,7 +13,7 @@
@@ -48,12 +47,11 @@
-
-
+
Add Google Maps on Customer
-
+ Share Information with
diff --git a/addons/crm_claim/res_config_view.xml b/addons/crm_claim/res_config_view.xml index bdcec2df43c..e0ca00103dc 100644 --- a/addons/crm_claim/res_config_view.xml +++ b/addons/crm_claim/res_config_view.xml @@ -11,7 +11,7 @@
-
diff --git a/addons/plugin_outlook/plugin_outlook.xml b/addons/plugin_outlook/plugin_outlook.xml index 428c7f2a649..381597824e1 100644 --- a/addons/plugin_outlook/plugin_outlook.xml +++ b/addons/plugin_outlook/plugin_outlook.xml @@ -54,7 +54,7 @@
-
diff --git a/addons/plugin_thunderbird/plugin_thunderbird.xml b/addons/plugin_thunderbird/plugin_thunderbird.xml index 5be79c069ff..f62c2f45187 100644 --- a/addons/plugin_thunderbird/plugin_thunderbird.xml +++ b/addons/plugin_thunderbird/plugin_thunderbird.xml @@ -60,7 +60,7 @@
-
diff --git a/addons/sale/res_config_view.xml b/addons/sale/res_config_view.xml index 8bead1c4411..66a3775fe14 100644 --- a/addons/sale/res_config_view.xml +++ b/addons/sale/res_config_view.xml @@ -15,24 +15,27 @@
- + From e027508ca272661f0faa48d542e59e0e4bb71ef5 Mon Sep 17 00:00:00 2001 From: Antonin Bourguignon Date: Wed, 1 Aug 2012 19:55:34 +0200 Subject: [PATCH 137/222] [IMP] use the .oe_separate-from-text class to separate the 'limit_amount' field from the rest of the label's text bzr revid: abo@openerp.com-20120801175534-x33mdgqmbhm5iu3s --- .../purchase_double_validation_installer.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/purchase_double_validation/purchase_double_validation_installer.xml b/addons/purchase_double_validation/purchase_double_validation_installer.xml index 2edabdce2b4..efba6bf9d76 100644 --- a/addons/purchase_double_validation/purchase_double_validation_installer.xml +++ b/addons/purchase_double_validation/purchase_double_validation_installer.xml @@ -9,10 +9,10 @@
-
From f468db471051b1533eddb56fc687b34ec1f3604c Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of openerp <> Date: Thu, 2 Aug 2012 04:46:16 +0000 Subject: [PATCH 138/222] Launchpad automatic translations update. bzr revid: launchpad_translations_on_behalf_of_openerp-20120802044616-pfibu91cnztf6r7c --- openerp/addons/base/i18n/ja.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openerp/addons/base/i18n/ja.po b/openerp/addons/base/i18n/ja.po index 77438be95df..2138a72fe03 100644 --- a/openerp/addons/base/i18n/ja.po +++ b/openerp/addons/base/i18n/ja.po @@ -8,13 +8,13 @@ msgstr "" "Project-Id-Version: openobject-server\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-02-08 00:44+0000\n" -"PO-Revision-Date: 2012-07-31 02:31+0000\n" +"PO-Revision-Date: 2012-08-01 23:52+0000\n" "Last-Translator: Akira Hiyama \n" "Language-Team: Japanese \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-01 04:43+0000\n" +"X-Launchpad-Export-Date: 2012-08-02 04:46+0000\n" "X-Generator: Launchpad (build 15719)\n" #. module: base @@ -3795,7 +3795,7 @@ msgstr "ホスト名またはSMTPサーバのIPアドレス" #. module: base #: selection:base.language.install,lang:0 msgid "Japanese / 日本語" -msgstr "Japanese / 日本語" +msgstr "日本語 / Japanese" #. module: base #: field:ir.actions.report.xml,auto:0 From 9fb21147c032ca96408fa0700f0d29981cbb2e9f Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of openerp <> Date: Thu, 2 Aug 2012 04:46:33 +0000 Subject: [PATCH 139/222] Launchpad automatic translations update. bzr revid: launchpad_translations_on_behalf_of_openerp-20120802044633-llw6r29ls6dty3l4 --- addons/account_check_writing/i18n/sv.po | 199 ++++++++++++++++++++++ addons/anonymization/i18n/sv.po | 213 ++++++++++++++++++++++++ addons/import_base/i18n/pt_BR.po | 2 +- 3 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 addons/account_check_writing/i18n/sv.po create mode 100644 addons/anonymization/i18n/sv.po diff --git a/addons/account_check_writing/i18n/sv.po b/addons/account_check_writing/i18n/sv.po new file mode 100644 index 00000000000..daff6998002 --- /dev/null +++ b/addons/account_check_writing/i18n/sv.po @@ -0,0 +1,199 @@ +# Swedish translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-02-08 00:35+0000\n" +"PO-Revision-Date: 2012-08-01 23:35+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Swedish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-08-02 04:46+0000\n" +"X-Generator: Launchpad (build 15719)\n" + +#. module: account_check_writing +#: selection:res.company,check_layout:0 +msgid "Check on Top" +msgstr "" + +#. module: account_check_writing +#: model:ir.actions.act_window,help:account_check_writing.action_write_check +msgid "" +"The check payment form allows you to track the payment you do to your " +"suppliers specially by check. When you select a supplier, the payment method " +"and an amount for the payment, OpenERP will propose to reconcile your " +"payment with the open supplier invoices or bills.You can print the check" +msgstr "" + +#. module: account_check_writing +#: view:account.voucher:0 +#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_bottom +#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_middle +#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_top +msgid "Print Check" +msgstr "Skriv ut check" + +#. module: account_check_writing +#: selection:res.company,check_layout:0 +msgid "Check in middle" +msgstr "" + +#. module: account_check_writing +#: help:res.company,check_layout:0 +msgid "" +"Check on top is compatible with Quicken, QuickBooks and Microsoft Money. " +"Check in middle is compatible with Peachtree, ACCPAC and DacEasy. Check on " +"bottom is compatible with Peachtree, ACCPAC and DacEasy only" +msgstr "" + +#. module: account_check_writing +#: selection:res.company,check_layout:0 +msgid "Check on bottom" +msgstr "" + +#. module: account_check_writing +#: constraint:res.company:0 +msgid "Error! You can not create recursive companies." +msgstr "Fel! Du kan inte skapa rekursiva företag." + +#. module: account_check_writing +#: help:account.journal,allow_check_writing:0 +msgid "Check this if the journal is to be used for writing checks." +msgstr "" + +#. module: account_check_writing +#: field:account.journal,allow_check_writing:0 +msgid "Allow Check writing" +msgstr "" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Description" +msgstr "Beskrivning" + +#. module: account_check_writing +#: model:ir.model,name:account_check_writing.model_account_journal +msgid "Journal" +msgstr "Journal" + +#. module: account_check_writing +#: model:ir.actions.act_window,name:account_check_writing.action_write_check +#: model:ir.ui.menu,name:account_check_writing.menu_action_write_check +msgid "Write Checks" +msgstr "" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Discount" +msgstr "Rabatt" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Original Amount" +msgstr "Ursprungligt belopp" + +#. module: account_check_writing +#: view:res.company:0 +msgid "Configuration" +msgstr "" + +#. module: account_check_writing +#: field:account.voucher,allow_check:0 +msgid "Allow Check Writing" +msgstr "" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Payment" +msgstr "Betalning" + +#. module: account_check_writing +#: field:account.journal,use_preprint_check:0 +msgid "Use Preprinted Check" +msgstr "" + +#. module: account_check_writing +#: sql_constraint:res.company:0 +msgid "The company name must be unique !" +msgstr "" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Due Date" +msgstr "" + +#. module: account_check_writing +#: model:ir.model,name:account_check_writing.model_res_company +msgid "Companies" +msgstr "Företag" + +#. module: account_check_writing +#: view:res.company:0 +msgid "Default Check Layout" +msgstr "" + +#. module: account_check_writing +#: constraint:account.journal:0 +msgid "" +"Configuration error! The currency chosen should be shared by the default " +"accounts too." +msgstr "" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +msgid "Balance Due" +msgstr "" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Check Amount" +msgstr "" + +#. module: account_check_writing +#: model:ir.model,name:account_check_writing.model_account_voucher +msgid "Accounting Voucher" +msgstr "" + +#. module: account_check_writing +#: sql_constraint:account.journal:0 +msgid "The name of the journal must be unique per company !" +msgstr "Journalnamnet måste vara unikt per företag!" + +#. module: account_check_writing +#: sql_constraint:account.journal:0 +msgid "The code of the journal must be unique per company !" +msgstr "Journalkoden måste vara unik per företag!" + +#. module: account_check_writing +#: field:account.voucher,amount_in_word:0 +msgid "Amount in Word" +msgstr "" + +#. module: account_check_writing +#: report:account.print.check.top:0 +msgid "Open Balance" +msgstr "" + +#. module: account_check_writing +#: field:res.company,check_layout:0 +msgid "Choose Check layout" +msgstr "" diff --git a/addons/anonymization/i18n/sv.po b/addons/anonymization/i18n/sv.po new file mode 100644 index 00000000000..cf315371912 --- /dev/null +++ b/addons/anonymization/i18n/sv.po @@ -0,0 +1,213 @@ +# Swedish translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-02-08 00:35+0000\n" +"PO-Revision-Date: 2012-08-02 00:12+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Swedish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-08-02 04:46+0000\n" +"X-Generator: Launchpad (build 15719)\n" + +#. module: anonymization +#: model:ir.model,name:anonymization.model_ir_model_fields_anonymize_wizard +msgid "ir.model.fields.anonymize.wizard" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization,field_name:0 +msgid "Field Name" +msgstr "Fältnamn" + +#. module: anonymization +#: field:ir.model.fields.anonymization,field_id:0 +msgid "Field" +msgstr "Fält" + +#. module: anonymization +#: field:ir.model.fields.anonymization.history,state:0 +#: field:ir.model.fields.anonymize.wizard,state:0 +msgid "State" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymize.wizard,file_import:0 +msgid "Import" +msgstr "Import" + +#. module: anonymization +#: model:ir.model,name:anonymization.model_ir_model_fields_anonymization +msgid "ir.model.fields.anonymization" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.history,direction:0 +msgid "Direction" +msgstr "" + +#. module: anonymization +#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymization_tree +#: view:ir.model.fields.anonymization:0 +#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_fields +msgid "Anonymized Fields" +msgstr "" + +#. module: anonymization +#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization +msgid "Database anonymization" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,direction:0 +msgid "clear -> anonymized" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization,state:0 +#: selection:ir.model.fields.anonymize.wizard,state:0 +msgid "Anonymized" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization,state:0 +msgid "unknown" +msgstr "okänd" + +#. module: anonymization +#: field:ir.model.fields.anonymization,model_id:0 +msgid "Object" +msgstr "Object" + +#. module: anonymization +#: field:ir.model.fields.anonymization.history,filepath:0 +msgid "File path" +msgstr "Sökväg" + +#. module: anonymization +#: field:ir.model.fields.anonymization.history,date:0 +msgid "Date" +msgstr "Datum" + +#. module: anonymization +#: field:ir.model.fields.anonymize.wizard,file_export:0 +msgid "Export" +msgstr "Export" + +#. module: anonymization +#: view:ir.model.fields.anonymize.wizard:0 +msgid "Reverse the Database Anonymization" +msgstr "" + +#. module: anonymization +#: view:ir.model.fields.anonymize.wizard:0 +msgid "Database Anonymization" +msgstr "" + +#. module: anonymization +#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_wizard +msgid "Anonymize database" +msgstr "" + +#. module: anonymization +#: view:ir.model.fields.anonymization.history:0 +#: field:ir.model.fields.anonymization.history,field_ids:0 +msgid "Fields" +msgstr "Fält" + +#. module: anonymization +#: selection:ir.model.fields.anonymization,state:0 +#: selection:ir.model.fields.anonymize.wizard,state:0 +msgid "Clear" +msgstr "Rensa" + +#. module: anonymization +#: view:ir.model.fields.anonymize.wizard:0 +#: field:ir.model.fields.anonymize.wizard,summary:0 +msgid "Summary" +msgstr "" + +#. module: anonymization +#: view:ir.model.fields.anonymization:0 +msgid "Anonymized Field" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymize.wizard,state:0 +msgid "Unstable" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,state:0 +msgid "Exception occured" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization,state:0 +#: selection:ir.model.fields.anonymize.wizard,state:0 +msgid "Not Existing" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization,model_name:0 +msgid "Object Name" +msgstr "Objektnamn" + +#. module: anonymization +#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymization_history_tree +#: view:ir.model.fields.anonymization.history:0 +#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_history +msgid "Anonymization History" +msgstr "" + +#. module: anonymization +#: model:ir.model,name:anonymization.model_ir_model_fields_anonymization_history +msgid "ir.model.fields.anonymization.history" +msgstr "" + +#. module: anonymization +#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymize_wizard +#: view:ir.model.fields.anonymize.wizard:0 +msgid "Anonymize Database" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymize.wizard,name:0 +msgid "File Name" +msgstr "Filnamn" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,direction:0 +msgid "anonymized -> clear" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,state:0 +msgid "Started" +msgstr "Påbörjad" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,state:0 +msgid "Done" +msgstr "Färdig" + +#. module: anonymization +#: view:ir.model.fields.anonymization.history:0 +#: field:ir.model.fields.anonymization.history,msg:0 +#: field:ir.model.fields.anonymize.wizard,msg:0 +msgid "Message" +msgstr "Meddelande" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:55 +#: sql_constraint:ir.model.fields.anonymization:0 +#, python-format +msgid "You cannot have two fields with the same name on the same object!" +msgstr "" diff --git a/addons/import_base/i18n/pt_BR.po b/addons/import_base/i18n/pt_BR.po index 9587acd607f..f301b8834ca 100644 --- a/addons/import_base/i18n/pt_BR.po +++ b/addons/import_base/i18n/pt_BR.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-01 04:44+0000\n" +"X-Launchpad-Export-Date: 2012-08-02 04:46+0000\n" "X-Generator: Launchpad (build 15719)\n" #. module: import_base From 07d748787b6e3ba3d0722645e32f7e95060f06a8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 2 Aug 2012 09:40:06 +0200 Subject: [PATCH 140/222] [IMP] make clicking of the 'Add a row' row in m2os save&create if there's a row being edited as requested by apr bzr revid: xmo@openerp.com-20120802074006-d843c10g9jal4nre --- addons/web/static/src/js/view_form.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 0aabfbb5480..8aa5ba7b743 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -3488,10 +3488,23 @@ instance.web.form.One2ManyList = instance.web.ListView.List.extend({ colspan: columns, 'class': 'oe_form_field_one2many_list_row_add' }).text(_t("Add a row")) + .mousedown(function () { + // FIXME: needs to be an official API somehow + if (self.view.editor.is_editing()) { + self.view.__ignore_blur = true; + } + }) .click(function (e) { e.preventDefault(); e.stopPropagation(); - self.view.do_add_record(); + // FIXME: there should also be an API for that one + if (self.view.editor.form.__blur_timeout) { + clearTimeout(self.view.editor.form.__blur_timeout); + self.view.editor.form.__blur_timeout = false; + } + self.view.ensure_saved().then(function () { + self.view.do_add_record(); + }); }); this.$current.append( $('').append($cell)) From 11dd44ec360d4130c824bda10bd2bee1f8a31a2c Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 2 Aug 2012 10:01:32 +0200 Subject: [PATCH 141/222] [TYPO] Set the right category for the Point Of Sale bzr revid: stw@openerp.com-20120802080132-6pt5s43sn6je9bul --- openerp/addons/base/module/module_data.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/module/module_data.xml b/openerp/addons/base/module/module_data.xml index cbe7a937eb6..ecd5226ad89 100644 --- a/openerp/addons/base/module/module_data.xml +++ b/openerp/addons/base/module/module_data.xml @@ -91,7 +91,7 @@ - Point of Sales + Point of Sale Helps you get the most out of your points of sales with fast sale encoding, simplified payment mode encoding, automatic picking lists generation and more. 13 From 2311c51782d5e1bafa64345d085057f82f6122f5 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 2 Aug 2012 10:23:35 +0200 Subject: [PATCH 142/222] [IMP] base: use the shortdesc in the search view of the modules bzr revid: stw@openerp.com-20120802082335-60u9wfqibfkzlk41 --- openerp/addons/base/module/module_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/module/module_view.xml b/openerp/addons/base/module/module_view.xml index e24c432d124..63af792ed8b 100644 --- a/openerp/addons/base/module/module_view.xml +++ b/openerp/addons/base/module/module_view.xml @@ -42,7 +42,7 @@ - + From 1f1770ffb782331b20b05b390348b3240faef393 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 2 Aug 2012 11:39:17 +0200 Subject: [PATCH 143/222] [IMP] Disable autofocus on editable lists bzr revid: fme@openerp.com-20120802093917-3wc9qgek6e2mba5p --- addons/web/static/src/js/view_list_editable.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 6c38495d0dc..67909f9c749 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -602,6 +602,7 @@ openerp.web.list_editable = function (instance) { this.form = new (this.options.formView)( this, this.delegate.dataset, false, { initial_mode: 'edit', + disable_autofocus: true, $buttons: $(), $pager: $() }); From 152cc49c3fcefc6e5678cacf85ca5d2455a11f0a Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 2 Aug 2012 11:53:26 +0200 Subject: [PATCH 144/222] [FIX] Autofocus on create mode bzr revid: fme@openerp.com-20120802095326-o6gc8jyvd44u9xg2 --- addons/web/static/src/js/view_form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 67f1b5c5629..1132d096d03 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -661,7 +661,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM } }, autofocus: function() { - if (this.get("actual_mode") === "edit" && !this.options.disable_autofocus) { + if (this.get("actual_mode") !== "view" && !this.options.disable_autofocus) { var fields_order = this.fields_order.slice(0); if (this.default_focus_field) { fields_order.unshift(this.default_focus_field.name); From 84bf640e67508b30c792664f2f8fe895646cd1a5 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 2 Aug 2012 12:00:20 +0200 Subject: [PATCH 145/222] [IMP] when trying to focus the first visible field in the editable list view, ensure that we only stop when we actually manage to focus a field bzr revid: xmo@openerp.com-20120802100020-kbmo1s5shjwaof69 --- addons/web/static/src/js/view_list_editable.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 6c38495d0dc..df3747717ee 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -681,9 +681,8 @@ openerp.web.list_editable = function (instance) { if (!field.$element.is(':visible')) { return false; } - field.focus(); // Stop as soon as a field got focused - return true; + return field.focus() !== false; }); }, edit: function (record, configureField, options) { From d08aa644f34391dcfbe1d2867d792ce0affa6a6f Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 2 Aug 2012 12:15:40 +0200 Subject: [PATCH 146/222] [REM] Removed a[type=edit, target=dialog] feature from kanban view. Speeds up kanban view bzr revid: fme@openerp.com-20120802101540-fjumv01o7oe1k7xh --- addons/web_kanban/static/src/js/kanban.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 4b6a4c9b158..3a03e7bc911 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -29,8 +29,6 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ records : {} }; this.groups = []; - this.form_dialog = new instance.web.form.FormDialog(this, {}, this.options.action_views_ids.form, dataset).start(); - this.form_dialog.on_form_dialog_saved.add_last(this.do_reload); this.aggregates = {}; this.group_operators = ['avg', 'max', 'min', 'sum', 'count']; this.qweb = new QWeb2.Engine(); @@ -704,14 +702,7 @@ instance.web_kanban.KanbanRecord = instance.web.OldWidget.extend({ return do_it(); }, do_action_edit: function($action) { - var self = this; - if ($action.attr('target') === 'dialog') { - this.view.form_dialog.select_id(this.id).then(function() { - self.view.form_dialog.open(); - }); - } else { - this.view.open_record(this.id, true); - } + this.view.open_record(this.id, true); }, do_action_object: function ($action) { var button_attrs = $action.data(); From 4c14e794d1b00a4efdf71eea6d7c4ee37ebe7ce2 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Thu, 2 Aug 2012 13:18:45 +0200 Subject: [PATCH 147/222] [IMP] Use the button_immediate_install in the form view of the modules bzr revid: stw@openerp.com-20120802111845-qgd2g6jkoxut0avl --- openerp/addons/base/module/module_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/module/module_view.xml b/openerp/addons/base/module/module_view.xml index 63af792ed8b..45d351a2125 100644 --- a/openerp/addons/base/module/module_view.xml +++ b/openerp/addons/base/module/module_view.xml @@ -116,7 +116,7 @@

-