Swiftorial Logo
Home
Swift Lessons
AI Tools
Learn More
Career
Resources

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:

  1. Traverse from the root to the target node to construct a path.
  2. Collect all capture listeners along this path from root to target (top-down).
  3. At the target node, include both capture and bubble listeners.
  4. Then traverse from the target back up to the root (bottom-up) to collect all bubble listeners.

📥 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 targetId and record the full path taken to get there.
  • Capture Listeners: Since capture phase is top-down, we add the capture listeners 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 bubble listeners.
  • 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.