Implement a delegate(root, selector, eventType, handler) utility for DOM event delegation.
Requirements
1. Delegate Matching Events
- Attach one listener to
root for eventType. - When an event bubbles from a descendant that matches
selector, call handler. - If the direct target does not match but one of its ancestors before
root does, treat that ancestor as the match.
2. Handler Contract
- Call
handler with this bound to the matched element. - Pass the original event as the first argument.
- Attach
event.delegateTarget to the matched element before calling the handler.
3. Cleanup
- Return an unsubscribe function that removes the listener.
- After cleanup, future events should not call the handler.
4. Edge Cases
- Ignore events that originate outside
root. - Ignore events with no matching element.