summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorJoseph Caburnay <jcb@odoo.com>2020-02-17 11:33:17 +0000
committerPierre Masereel <pim@odoo.com>2020-02-20 12:33:54 +0000
commit2c383aae48b81597d3dae6318a3e8a8f56f6f6b8 (patch)
treee95c534ed1a6f8926a2a09d59c5f19a9a9f35c89 /addons
parent85f6290b68fdb01ed42b69e191b8aeb3689397b8 (diff)
[IMP] web: custom_hooks: useListener able to pass options to addEventListener
addEventListener supports an `options` argument, which can be useful to listen on events during the capture phase This commit allows to pass these options to the hook useListener closes odoo/odoo#45478 Signed-off-by: pimodoo <pimodoo@users.noreply.github.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/web/static/src/js/core/custom_hooks.js13
-rw-r--r--addons/web/static/tests/component_extension_tests.js67
2 files changed, 75 insertions, 5 deletions
diff --git a/addons/web/static/src/js/core/custom_hooks.js b/addons/web/static/src/js/core/custom_hooks.js
index a99576b73ce..c196dd7f900 100644
--- a/addons/web/static/src/js/core/custom_hooks.js
+++ b/addons/web/static/src/js/core/custom_hooks.js
@@ -66,13 +66,16 @@ odoo.define('web.custom_hooks', function () {
* @param {string} eventName the name of the event
* @param {string} [querySelector] a JS native selector for event delegation
* @param {function} handler the event handler (will be bound to the component)
+ * @param {Object} [addEventListenerOptions] to be passed to addEventListener as options.
+ * Useful for listening in the capture phase
*/
- function useListener(eventName, querySelector, handler) {
- if (arguments.length === 2) {
+ function useListener(eventName, querySelector, handler, addEventListenerOptions) {
+ if (typeof arguments[1] !== 'string') {
querySelector = null;
handler = arguments[1];
+ addEventListenerOptions = arguments[2];
}
- if (!(typeof handler === 'function')) {
+ if (typeof handler !== 'function') {
throw new Error('The handler must be a function');
}
@@ -99,10 +102,10 @@ odoo.define('web.custom_hooks', function () {
boundHandler = handler.bind(comp);
}
onMounted(function () {
- comp.el.addEventListener(eventName, boundHandler);
+ comp.el.addEventListener(eventName, boundHandler, addEventListenerOptions);
});
onWillUnmount(function () {
- comp.el.removeEventListener(eventName, boundHandler);
+ comp.el.removeEventListener(eventName, boundHandler, addEventListenerOptions);
});
}
diff --git a/addons/web/static/tests/component_extension_tests.js b/addons/web/static/tests/component_extension_tests.js
index f0b33db655c..08f5071ec04 100644
--- a/addons/web/static/tests/component_extension_tests.js
+++ b/addons/web/static/tests/component_extension_tests.js
@@ -181,5 +181,72 @@ odoo.define('web.component_extension_tests', function (require) {
parent.destroy();
fixture.classList.remove('custom-class');
});
+
+ QUnit.test("useListener with capture option", async function (assert) {
+ assert.expect(7);
+ const fixture = document.body.querySelector('#qunit-fixture');
+
+ class Leaf extends Component {
+ constructor() {
+ super();
+ useListener('custom1', this._onCustom1);
+ }
+ _onCustom1() {
+ assert.step(`${this.constructor.name} custom1`);
+ }
+ }
+ Leaf.template = xml`<div class="leaf"/>`;
+
+ class Root extends Component {
+ constructor() {
+ super();
+ useListener('custom1', this._onCustom1, { capture: true });
+ }
+ _onCustom1(event) {
+ assert.step(`${this.constructor.name} custom1`);
+ const detail = event.detail;
+ if (detail && detail.stopMe) {
+ event.stopPropagation();
+ }
+ }
+ }
+ Root.template = xml`<div class="root"><Leaf/></div>`;
+ Root.components = { Leaf };
+
+ const root = new Root(null);
+ await root.mount(fixture);
+
+ const rootNode = document.body.querySelector('.root');
+ const leafNode = document.body.querySelector('.leaf');
+ rootNode.dispatchEvent(new CustomEvent('custom1', {
+ bubbles: true,
+ cancelable: true
+ }));
+ assert.verifySteps(['Root custom1']);
+
+ // Dispatch custom1 on the leaf element.
+ // Since we listen in the capture phase, Root is first triggered.
+ // The event is stopped there.
+ leafNode.dispatchEvent(new CustomEvent('custom1', {
+ bubbles: true,
+ cancelable: true,
+ detail: {
+ stopMe: true
+ },
+ }));
+ assert.verifySteps(['Root custom1']);
+
+ // Same as before, except this time we don't stop the event
+ leafNode.dispatchEvent(new CustomEvent('custom1', {
+ bubbles: true,
+ cancelable: true,
+ detail: {
+ stopMe: false
+ }
+ }));
+ assert.verifySteps(['Root custom1', 'Leaf custom1']);
+
+ root.destroy();
+ });
});
});