mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] bdom: support multiple synthetic events on one node
This commit is contained in:
@@ -47,14 +47,18 @@ function createElementHandler(evName: string, capture: boolean = false): EventHa
|
|||||||
|
|
||||||
// Synthetic handler: a form of event delegation that allows placing only one
|
// Synthetic handler: a form of event delegation that allows placing only one
|
||||||
// listener per event type.
|
// listener per event type.
|
||||||
|
let nextSyntheticEventId = 1;
|
||||||
function createSyntheticHandler(evName: string, capture: boolean = false): EventHandlerCreator {
|
function createSyntheticHandler(evName: string, capture: boolean = false): EventHandlerCreator {
|
||||||
let eventKey = `__event__synthetic_${evName}`;
|
let eventKey = `__event__synthetic_${evName}`;
|
||||||
if (capture) {
|
if (capture) {
|
||||||
eventKey = `${eventKey}_capture`;
|
eventKey = `${eventKey}_capture`;
|
||||||
}
|
}
|
||||||
setupSyntheticEvent(evName, eventKey, capture);
|
setupSyntheticEvent(evName, eventKey, capture);
|
||||||
|
const currentId = nextSyntheticEventId++;
|
||||||
function setup(this: HTMLElement, data: any) {
|
function setup(this: HTMLElement, data: any) {
|
||||||
(this as any)[eventKey] = data;
|
const _data = (this as any)[eventKey] || {};
|
||||||
|
_data[currentId] = data;
|
||||||
|
(this as any)[eventKey] = _data;
|
||||||
}
|
}
|
||||||
return { setup, update: setup };
|
return { setup, update: setup };
|
||||||
}
|
}
|
||||||
@@ -62,11 +66,13 @@ function createSyntheticHandler(evName: string, capture: boolean = false): Event
|
|||||||
function nativeToSyntheticEvent(eventKey: string, event: Event) {
|
function nativeToSyntheticEvent(eventKey: string, event: Event) {
|
||||||
let dom = event.target;
|
let dom = event.target;
|
||||||
while (dom !== null) {
|
while (dom !== null) {
|
||||||
const data = (dom as any)[eventKey];
|
const _data = (dom as any)[eventKey];
|
||||||
if (data) {
|
if (_data) {
|
||||||
|
for (const data of Object.values(_data)) {
|
||||||
const stopped = config.mainEventHandler(data, event, dom);
|
const stopped = config.mainEventHandler(data, event, dom);
|
||||||
if (stopped) return;
|
if (stopped) return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
dom = (dom as any).parentNode;
|
dom = (dom as any).parentNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,6 +123,40 @@ test("two same block nodes with different handlers (synthetic)", async () => {
|
|||||||
expect(steps).toEqual(["1", "2"]);
|
expect(steps).toEqual(["1", "2"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("two event handlers on same event", async () => {
|
||||||
|
const block = createBlock('<div block-handler-0="click" block-handler-1="click"></div>');
|
||||||
|
let n = 0;
|
||||||
|
let m = 0;
|
||||||
|
const tree = block([() => m++, () => n++]);
|
||||||
|
|
||||||
|
mount(tree, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<div></div>");
|
||||||
|
|
||||||
|
expect(m).toBe(0);
|
||||||
|
expect(n).toBe(0);
|
||||||
|
(fixture.firstChild as HTMLDivElement).click();
|
||||||
|
expect(m).toBe(1);
|
||||||
|
expect(n).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("two synthetic event handlers on same event", async () => {
|
||||||
|
const block = createBlock(
|
||||||
|
'<div block-handler-0="click.synthetic" block-handler-1="click.synthetic"></div>'
|
||||||
|
);
|
||||||
|
let n = 0;
|
||||||
|
let m = 0;
|
||||||
|
const tree = block([() => m++, () => n++]);
|
||||||
|
|
||||||
|
mount(tree, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<div></div>");
|
||||||
|
|
||||||
|
expect(m).toBe(0);
|
||||||
|
expect(n).toBe(0);
|
||||||
|
(fixture.firstChild as HTMLDivElement).click();
|
||||||
|
expect(m).toBe(1);
|
||||||
|
expect(n).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
test("synthetic and native handlers can cohabitate", async () => {
|
test("synthetic and native handlers can cohabitate", async () => {
|
||||||
const block = createBlock(
|
const block = createBlock(
|
||||||
'<div block-handler-0="click.synthetic"><div block-handler-1="click"/></div>'
|
'<div block-handler-0="click.synthetic"><div block-handler-1="click"/></div>'
|
||||||
@@ -180,7 +214,7 @@ test("synthetic and native handlers can cohabitate (3)", async () => {
|
|||||||
expect(steps).toEqual(["1", "0", "0", "2"]);
|
expect(steps).toEqual(["1", "0", "0", "2"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("synthetic and native handlers can cohabitate (5)", async () => {
|
test("synthetic and native handlers can cohabitate (4)", async () => {
|
||||||
const parent = createBlock(`<div block-handler-0="click"><block-child-0/><block-child-1/></div>`);
|
const parent = createBlock(`<div block-handler-0="click"><block-child-0/><block-child-1/></div>`);
|
||||||
const block = createBlock('<div block-handler-0="click"/>');
|
const block = createBlock('<div block-handler-0="click"/>');
|
||||||
const blockSynth = createBlock('<div block-handler-0="click.synthetic"/>');
|
const blockSynth = createBlock('<div block-handler-0="click.synthetic"/>');
|
||||||
@@ -203,3 +237,37 @@ test("synthetic and native handlers can cohabitate (5)", async () => {
|
|||||||
(children[1] as HTMLElement).click();
|
(children[1] as HTMLElement).click();
|
||||||
expect(steps).toEqual(["1", "0", "0"]);
|
expect(steps).toEqual(["1", "0", "0"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("synthetic and native handlers can cohabitate (5)", async () => {
|
||||||
|
const block = createBlock('<div block-handler-0="click.synthetic" block-handler-1="click"/>');
|
||||||
|
let steps: string[] = [];
|
||||||
|
let handler1 = () => steps.push("1");
|
||||||
|
let handler2 = () => steps.push("2");
|
||||||
|
const tree = block([handler1, handler2]);
|
||||||
|
|
||||||
|
mount(tree, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<div></div>");
|
||||||
|
|
||||||
|
(fixture.firstChild as HTMLDivElement).click();
|
||||||
|
expect(steps).toEqual(["2", "1"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("synthetic and native handlers can cohabitate (6)", async () => {
|
||||||
|
const block = createBlock(`<div
|
||||||
|
block-handler-0="click.synthetic"
|
||||||
|
block-handler-1="click"
|
||||||
|
block-handler-2="click.synthetic"
|
||||||
|
block-handler-3="click"
|
||||||
|
/>`);
|
||||||
|
let steps: string[] = [];
|
||||||
|
const handler1 = () => steps.push("1");
|
||||||
|
const handler2 = () => steps.push("2");
|
||||||
|
const handler3 = () => steps.push("3");
|
||||||
|
const handler4 = () => steps.push("4");
|
||||||
|
const tree = block([handler1, handler2, handler3, handler4]);
|
||||||
|
mount(tree, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<div></div>");
|
||||||
|
|
||||||
|
(fixture.firstChild as HTMLDivElement).click();
|
||||||
|
expect(steps).toEqual(["2", "4", "1", "3"]);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user