[IMP] qweb: add support for event capture

In this commit, we uses the "!" as suffix to designate an event that
should be captured.  This is inspired by the Vue source code.

This solves the issue of communicating additional information to the
underlying virtual dom.  However, this will most likely disappear when
we rewrite the vdom as a virtual block system.

closes #650
This commit is contained in:
Géry Debongnie
2020-02-20 11:27:47 +01:00
committed by aab-odoo
parent 2c01802b8e
commit b00188c1ce
8 changed files with 140 additions and 12 deletions
+5
View File
@@ -299,6 +299,8 @@ QWeb.addDirective({
}
let eventsCode = events
.map(function([name, value]) {
const capture = name.match(/\.capture/);
name = capture ? name.replace(/\.capture/, "") : name;
const { event, handler } = makeHandlerCode(
ctx,
name,
@@ -306,6 +308,9 @@ QWeb.addDirective({
false,
T_COMPONENT_MODS_CODE
);
if (capture) {
return `vn.elm.addEventListener('${event}', ${handler}, true);`;
}
return `vn.elm.addEventListener('${event}', ${handler});`;
})
.join("");
+4 -1
View File
@@ -40,7 +40,10 @@ export function makeHandlerCode(
putInCache: boolean,
modcodes = MODS_CODE
): HandlerInfo {
const [event, ...mods] = fullName.slice(5).split(".");
let [event, ...mods] = fullName.slice(5).split(".");
if (mods.includes("capture")) {
event = "!" + event;
}
if (!event) {
throw new Error("Missing event name with t-on directive");
}
+18 -6
View File
@@ -70,8 +70,12 @@ function handleEvent(event: Event, vnode: VNode) {
on = (vnode.data as VNodeData).on;
// call event handler(s) if exists
if (on && on[name]) {
invokeHandler(on[name], vnode, event);
if (on) {
if (on[name]) {
invokeHandler(on[name], vnode, event);
} else if (on["!" + name]) {
invokeHandler(on["!" + name], vnode, event);
}
}
}
@@ -100,13 +104,17 @@ function updateEventListeners(oldVnode: VNode, vnode?: VNode): void {
if (!on) {
for (name in oldOn) {
// remove listener if element was changed or existing listeners removed
oldElm.removeEventListener(name, oldListener, false);
const capture = name.charAt(0) === "!";
name = capture ? name.slice(1) : name;
oldElm.removeEventListener(name, oldListener, capture);
}
} else {
for (name in oldOn) {
// remove listener if existing listener removed
if (!on[name]) {
oldElm.removeEventListener(name, oldListener, false);
const capture = name.charAt(0) === "!";
name = capture ? name.slice(1) : name;
oldElm.removeEventListener(name, oldListener, capture);
}
}
}
@@ -123,13 +131,17 @@ function updateEventListeners(oldVnode: VNode, vnode?: VNode): void {
if (!oldOn) {
for (name in on) {
// add listener if element was changed or new listeners added
elm.addEventListener(name, listener, false);
const capture = name.charAt(0) === "!";
name = capture ? name.slice(1) : name;
elm.addEventListener(name, listener, capture);
}
} else {
for (name in on) {
// add listener if new listener added
if (!oldOn[name]) {
elm.addEventListener(name, listener, false);
const capture = name.charAt(0) === "!";
name = capture ? name.slice(1) : name;
elm.addEventListener(name, listener, capture);
}
}
}