Run order of click listeners on a page

Write codeEasy15 min

Your task

A click is delivered along a path of elements: down from the root to the element that was clicked, then back up. Your team's test harness replays that path without a browser, to check which handlers run.

Write click_order(path, listeners) that returns the names of the listeners that run, in the order they run.

Input and output:

  • path: the element ids from the root down to the clicked element (the target), 1 to 50 ids, all different.
  • listeners: up to 200 listeners, in the order they were added. Each is [element, capture, name, action]. element is the id of the element the listener is on. capture is true for a capture listener and false for a bubble listener. That is the listener's kind. action is "", "stop" or "stop_now".
  • Returns a list of names, one for each listener that runs. Names can repeat.

Rules:

  • Capture comes first: for each element from the root down to the target's parent, its capture listeners run.
  • Then the target: its capture listeners run, then its bubble listeners.
  • Then bubble: for each element from the target's parent up to the root, its bubble listeners run.
  • Listeners of the same kind on the same element run in the order they were added. Listeners on elements outside path never run.
  • "stop" stands for a call to stopPropagation(). The remaining listeners of the same kind on the same element still run, and then nothing else does. At the target, capture and bubble listeners are different kinds, so a "stop" in one of the target's capture listeners also skips the target's bubble listeners.
  • "stop_now" stands for a call to stopImmediatePropagation(). Nothing runs after that listener.

Examples

click_order(path: list[str], listeners: list[list]) -> list[str]
Example 1
Inputclick_order(["html", "body", "form", "button"], [["html", True, "log-capture", ""], ["body", False, "close-menus", ""], ["form", True, "track-form", ""], ["button", False, "submit", ""], ["button", True, "ripple", ""], ["form", False, "validate", ""], ["html", False, "analytics", ""]])
Output["log-capture", "track-form", "ripple", "submit", "validate", "close-menus", "analytics"]
Example 2
Inputclick_order(["html", "body", "form", "button"], [["body", True, "focus-guard", "stop"], ["body", True, "trace", ""], ["form", True, "track-form", ""], ["button", False, "submit", ""], ["body", False, "close-menus", ""]])
Output["focus-guard", "trace"]
Example 3
Inputclick_order(["app", "list", "row"], [["row", False, "select-row", "stop_now"], ["row", False, "open-row", ""], ["list", False, "list-click", ""], ["app", True, "app-capture", ""]])
Output["app-capture", "select-row"]