-
Notifications
You must be signed in to change notification settings - Fork 359
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IMP] component: add support for t-on on compnents
- Loading branch information
1 parent
67f86a4
commit 50355e6
Showing
12 changed files
with
349 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { createEventHandler } from "./events"; | ||
import type { VNode } from "./index"; | ||
|
||
type EventsSpec = { [name: string]: number }; | ||
|
||
type Catcher = (child: VNode, handlers: any[]) => VNode; | ||
|
||
export function createCatcher(eventsSpec: EventsSpec): Catcher { | ||
let setupFns: any[] = []; | ||
let removeFns: any[] = []; | ||
for (let name in eventsSpec) { | ||
let index = eventsSpec[name]; | ||
let { setup, remove } = createEventHandler(name); | ||
setupFns[index] = setup; | ||
removeFns[index] = remove; | ||
} | ||
let n = setupFns.length; | ||
|
||
class VCatcher { | ||
child: VNode; | ||
handlers: any[]; | ||
|
||
parentEl?: HTMLElement | undefined; | ||
afterNode: Node | null = null; | ||
|
||
constructor(child: VNode, handlers: any[]) { | ||
this.child = child; | ||
this.handlers = handlers; | ||
} | ||
|
||
mount(parent: HTMLElement, afterNode: Node | null) { | ||
this.parentEl = parent; | ||
this.afterNode = afterNode; | ||
this.child.mount(parent, afterNode); | ||
for (let i = 0; i < n; i++) { | ||
let origFn = this.handlers[i][0]; | ||
const self = this; | ||
this.handlers[i][0] = function (ev: any) { | ||
const target = ev.target; | ||
let currentNode: any = self.child.firstNode(); | ||
const afterNode = self.afterNode; | ||
while (currentNode !== afterNode) { | ||
if (currentNode.contains(target)) { | ||
return origFn.call(this, ev); | ||
} | ||
currentNode = currentNode.nextSibling; | ||
} | ||
}; | ||
setupFns[i].call(parent, this.handlers[i]); | ||
} | ||
} | ||
|
||
moveBefore(other: VCatcher | null, afterNode: Node | null) { | ||
this.afterNode = null; | ||
this.child.moveBefore(other ? other.child : null, afterNode); | ||
} | ||
|
||
patch(other: VCatcher, withBeforeRemove: boolean) { | ||
if (this === other) { | ||
return; | ||
} | ||
this.handlers = other.handlers; | ||
this.child.patch(other.child, withBeforeRemove); | ||
} | ||
|
||
beforeRemove() { | ||
this.child.beforeRemove(); | ||
} | ||
|
||
remove() { | ||
for (let i = 0; i < n; i++) { | ||
removeFns[i].call(this.parentEl!); | ||
} | ||
this.child.remove(); | ||
} | ||
|
||
firstNode(): Node | undefined { | ||
return this.child.firstNode(); | ||
} | ||
|
||
toString(): string { | ||
return this.child.toString(); | ||
} | ||
} | ||
|
||
return function (child: VNode, handlers: any[]): VNode<VCatcher> { | ||
return new VCatcher(child, handlers); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { config, createBlock, createCatcher, mount } from "../../src/blockdom"; | ||
import { makeTestFixture } from "./helpers"; | ||
import { mainEventHandler } from "../../src/component/handler"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Setup and helpers | ||
//------------------------------------------------------------------------------ | ||
|
||
let fixture: HTMLElement; | ||
config.mainEventHandler = mainEventHandler; | ||
|
||
beforeEach(() => { | ||
fixture = makeTestFixture(); | ||
}); | ||
|
||
afterEach(() => { | ||
fixture.remove(); | ||
}); | ||
|
||
test("simple event catcher", async () => { | ||
const catcher = createCatcher({ click: 0 }); | ||
const block = createBlock("<div></div>"); | ||
let n = 0; | ||
let ctx = {}; | ||
let handler = [() => n++, ctx]; | ||
const tree = catcher(block(), [handler]); | ||
|
||
mount(tree, fixture); | ||
expect(fixture.innerHTML).toBe("<div></div>"); | ||
|
||
expect(fixture.firstChild).toBeInstanceOf(HTMLDivElement); | ||
expect(n).toBe(0); | ||
(fixture.firstChild as HTMLDivElement).click(); | ||
expect(n).toBe(1); | ||
}); | ||
|
||
test("do not catch events outside of itself", async () => { | ||
const catcher = createCatcher({ click: 0 }); | ||
const childBlock = createBlock("<div></div>"); | ||
const parentBlock = createBlock("<button><block-child-0/></button>"); | ||
let n = 0; | ||
let ctx = {}; | ||
let handler = [() => n++, ctx]; | ||
const tree = parentBlock([], [catcher(childBlock(), [handler])]); | ||
|
||
mount(tree, fixture); | ||
expect(fixture.innerHTML).toBe("<button><div></div></button>"); | ||
|
||
expect(n).toBe(0); | ||
fixture.querySelector("div")!.click(); | ||
expect(n).toBe(1); | ||
fixture.querySelector("button")!.click(); | ||
expect(n).toBe(1); | ||
}); |
Oops, something went wrong.