diff --git a/addons/web/static/src/js/framework/mixins.js b/addons/web/static/src/js/framework/mixins.js index 68c19f6b9f4..e9f9b2c94b0 100644 --- a/addons/web/static/src/js/framework/mixins.js +++ b/addons/web/static/src/js/framework/mixins.js @@ -114,6 +114,22 @@ var ParentedMixin = { }, }; +function OdooEvent (target, name, data) { + this.target = target; + this.name = name; + this.data = Object.create(null); + _.extend(this.data, data); + this.stopped = false; +} + +OdooEvent.prototype.stop_propagation = function () { + this.stopped = true; +}; + +OdooEvent.prototype.is_stopped = function () { + return this.stopped; +}; + /** * Backbone's events. Do not ever use it directly, use EventDispatcherMixin instead. * @@ -256,6 +272,16 @@ var EventDispatcherMixin = _.extend({}, ParentedMixin, { this.__edispatcherEvents.trigger.apply(this.__edispatcherEvents, arguments); return this; }, + trigger_up: function(name, info) { + var event = new OdooEvent(this, name, info); + this._trigger_up(event); + }, + _trigger_up: function(event) { + this.__edispatcherEvents.trigger(event.name, event); + if (!event.is_stopped() && (parent = this.getParent())) { + parent._trigger_up(event); + } + }, destroy: function() { var self = this; _.each(this.__edispatcherRegisteredEvents, function(event) { diff --git a/addons/web/static/src/js/framework/widget.js b/addons/web/static/src/js/framework/widget.js index ad68f4e9410..f606e8482ca 100644 --- a/addons/web/static/src/js/framework/widget.js +++ b/addons/web/static/src/js/framework/widget.js @@ -64,6 +64,7 @@ var Widget = core.Class.extend(mixins.PropertiesMixin, { className: null, attributes: {}, events: {}, + custom_events: {}, /** * The name of the QWeb template that will be used for rendering. Must be * redefined in subclasses or the default render() method can not be used. @@ -94,6 +95,7 @@ var Widget = core.Class.extend(mixins.PropertiesMixin, { } // FIXME: this should not be this.setElement(this._make_descriptive()); + this.delegateCustomEvents(); }, /** * Method called between init and start. Performs asynchronous calls required by start. @@ -303,6 +305,21 @@ var Widget = core.Class.extend(mixins.PropertiesMixin, { } } }, + delegateCustomEvents: function () { + if (_.isEmpty(this.custom_events)) { return; } + for (var key in this.custom_events) { + if (!this.custom_events.hasOwnProperty(key)) { continue; } + + var method = this.proxy(this.custom_events[key]); + this.on(key, this, wrap_handler(method)); + } + function wrap_handler(callback) { + return function (event) { + event.stop_propagation(); + callback(event); + }; + } + }, undelegateEvents: function () { this.$el.off('.widget_events'); },