- 새 공용 ui_template_window_watch(listenWhileAlive) — 창 · 문서 듣개는 종류마다 하나 · 화면 노드는 약하게 쥠 · 노드가 버려지면 저절로 빠짐 - design_leave beforeunload · overlay_drag pointermove · pointerup · pointercancel · resize · Panel_Settings document pointerup · keyup · side_panels scroll · resize 를 노드 수명으로 - side_panels 크기 감시가 place 를 약하게 쥠(감시가 노드를 안 붙듦) - 코리도 모듈 캐시 = 지금 노선 한 칸 - 시험 test_298_3_page_dispose(다섯 번 다시 세움 뒤 창 듣개 수 그대로 · 옛 노드 풀림) · helper_346_4 새 모듈 읽기 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
55 lines
1.9 KiB
TypeScript
55 lines
1.9 KiB
TypeScript
/* =============================================================================
|
|
* ui_template/ui_template_window_watch.ts
|
|
* 창 · 문서 듣기를 화면 노드 수명에 묶음(298-3) — 종류마다 듣개 하나만 걸고 노드는 약하게 쥠.
|
|
* 페이지를 다시 세워도(노선 [저장]) 옛 페이지를 붙들지 않고 창 듣개 수가 늘지 않음.
|
|
* 노드가 살아 있는 동안은 떼었다 다시 붙여도(M01) 계속 들음 · 버려지면 저절로 빠짐.
|
|
* ========================================================================== */
|
|
|
|
type Call = (event: Event) => void;
|
|
|
|
interface Hub {
|
|
nodes: Set<WeakRef<object>>;
|
|
/** 노드 → 부를 것 — 값이 노드를 쥐어도 노드와 함께 풀림(WeakMap). */
|
|
calls: WeakMap<object, Call[]>;
|
|
}
|
|
|
|
const hubs = new WeakMap<EventTarget, Map<string, Hub>>();
|
|
|
|
function hubOf(target: EventTarget, type: string, capture: boolean): Hub {
|
|
let byType = hubs.get(target);
|
|
if (!byType) hubs.set(target, (byType = new Map()));
|
|
const key = `${type}:${capture}`;
|
|
const found = byType.get(key);
|
|
if (found) return found;
|
|
const hub: Hub = { nodes: new Set(), calls: new WeakMap() };
|
|
target.addEventListener(
|
|
type,
|
|
(event) =>
|
|
hub.nodes.forEach((ref) => {
|
|
const node = ref.deref();
|
|
if (!node) hub.nodes.delete(ref);
|
|
else hub.calls.get(node)?.forEach((call) => call(event));
|
|
}),
|
|
capture,
|
|
);
|
|
byType.set(key, hub);
|
|
return hub;
|
|
}
|
|
|
|
/** `target` 의 `type` 을 `node` 가 살아 있는 동안 들음. */
|
|
export function listenWhileAlive<E extends Event = Event>(
|
|
target: EventTarget,
|
|
type: string,
|
|
node: object,
|
|
call: (event: E) => void,
|
|
capture = false,
|
|
): void {
|
|
const hub = hubOf(target, type, capture);
|
|
const calls = hub.calls.get(node);
|
|
if (calls) calls.push(call as Call);
|
|
else {
|
|
hub.calls.set(node, [call as Call]);
|
|
hub.nodes.add(new WeakRef(node));
|
|
}
|
|
}
|