[IMP] bdom: support multiple synthetic events on one node

This commit is contained in:
Bruno Boi
2021-11-08 12:12:44 +01:00
committed by Géry Debongnie
parent 8d4eb21536
commit 84913593b2
2 changed files with 81 additions and 6 deletions
+12 -5
View File
@@ -47,14 +47,17 @@ 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; (this as any)[eventKey] = (this as any)[eventKey] || {};
(this as any)[eventKey][currentId] = data;
} }
return { setup, update: setup }; return { setup, update: setup };
} }
@@ -62,10 +65,14 @@ 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 datas = (dom as any)[eventKey];
if (data) { if (datas) {
const stopped = config.mainEventHandler(data, event, dom); for (const data of Object.values(datas)) {
if (stopped) return; if (data) {
const stopped = config.mainEventHandler(data, event, dom);
if (stopped) return;
}
}
} }
dom = (dom as any).parentNode; dom = (dom as any).parentNode;
} }
+69 -1
View File
@@ -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"]);
});