Data Structures & Algorithms FAQ: Top Questions
1. Simulate Event Propagation in a DOM Tree
In the browser environment, events are dispatched through the DOM using a mechanism called event propagation, which consists of two main phases:
- Capture Phase (Capturing): The event travels from the root of the DOM tree down to the target node.
- Bubbling Phase (Bubbling): After reaching the target, the event bubbles back up to the root.
This simulation mimics that process using a tree-like JavaScript object. Our goal is to output the exact order in which the registered event listeners are triggered.
🧭 Step-by-Step Instructions:
- Traverse from the root to the target node to construct a path.
- Collect all
capturelisteners along this path from root to target (top-down). - At the target node, include both
captureandbubblelisteners. - Then traverse from the target back up to the root (bottom-up) to collect all
bubblelisteners.
📥 Example Input:
This example represents a simplified DOM structure with nested nodes and associated event listeners.
const domTree = {
id: "root",
listeners: { capture: ["logRootCapture"], bubble: ["logRootBubble"] },
children: [{
id: "parent",
listeners: { capture: ["logParentCapture"], bubble: ["logParentBubble"] },
children: [{
id: "child",
listeners: { capture: ["logChildCapture"], bubble: ["logChildBubble"] },
children: []
}]
}]
};
const targetId = "child";
🎯 Expected Output:
The order in which listeners should be called when the event targets the child node:
[
"logRootCapture",
"logParentCapture",
"logChildCapture",
"logChildBubble",
"logParentBubble",
"logRootBubble"
]
✅ TypeScript Solution (with Explanation):
type Node = {
id: string;
listeners?: { capture?: string[]; bubble?: string[] };
children: Node[];
};
function simulateEventPropagation(tree: Node, targetId: string): string[] {
const path: Node[] = [];
// Step 1: Depth-First Search to locate target and record the path
function dfs(node: Node, currentPath: Node[]): boolean {
currentPath.push(node);
if (node.id === targetId) {
path.push(...currentPath); // Save full path to target
return true;
}
for (const child of node.children) {
if (dfs(child, [...currentPath])) return true;
}
return false;
}
// Start DFS from the root
dfs(tree, []);
const result: string[] = [];
// Step 2: Traverse path top-down to collect capture listeners
for (const node of path) {
if (node.listeners?.capture) {
result.push(...node.listeners.capture);
}
}
// Step 3: Traverse path bottom-up to collect bubble listeners
for (let i = path.length - 1; i >= 0; i--) {
const node = path[i];
if (node.listeners?.bubble) {
result.push(...node.listeners.bubble);
}
}
return result;
}
📘 Detailed Explanation:
- DFS Traversal: The DFS (Depth-First Search) is used to find the node with the given
targetIdand record the full path taken to get there. - Capture Listeners: Since capture phase is top-down, we add the
capturelisteners while traversing the path from the root to the target. - Bubble Listeners: Since bubbling is bottom-up, we reverse-traverse the path from the target back to the root and collect
bubblelisteners. - Path Cloning: In DFS, we clone the path array to avoid mutating state across recursion branches.
🛠️ Use Cases:
- Understanding browser event propagation for frontend development.
- Building virtual DOMs or synthetic event systems.
- Simulating or debugging custom tree-based event architectures.
