twbs / twbs/bootstrap

Simplify `bootstrapDelegationHandler` using `Element.closest`

Open
#41,116 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature js v5
Dominant language
MDX
Stars
175k
Forks
78.6k
Avg merge
7h 19m
Merged PRs (30d)
35

Description

Prerequisites
Proposal

Hello Bootstrap team,

I have a suggestion to simplify and potentially optimize the bootstrapDelegationHandler function in event-handler.js.

Current Behavior

https://github.com/twbs/bootstrap/blob/0cbfe13adf669ad39ae9d8e873c2ad59befd3a3a/js/src/dom/event-handler.js#L102-L122

The bootstrapDelegationHandler function is invoked when the third argument of the EventHandler.on method, handler, is a selector string. It is widely used to detect components like carousel, collapse, dropdown, modal, offcanvas, and tab based on their data attributes. In these cases, the first argument of bootstrapDelegationHandler, element, is typically set to document.

For example:
https://github.com/twbs/bootstrap/blob/0cbfe13adf669ad39ae9d8e873c2ad59befd3a3a/js/src/dropdown.js#L444

As a result, Bootstrap executes multiple DOM selector queries against the entire DOM tree every time an event is triggered to check if the event is related to a specific component. For instance, with click events in the default bundle (loading all components), this can result in 11 DOM queries, causing noticeable delays depending on the DOM tree size and the user's device.

Motivation and context

Proposed Implementation

I suggest replacing the current DOM traversal logic with the more efficient Element.closest method, which simplifies the implementation and improves performance. Here's the proposed code:

function bootstrapDelegationHandler(element, selector, fn) {
  return function handler(event) {
    const target = event.target.closest(selector);

    if (target && element.contains(target)) {
      hydrateObj(event, { delegateTarget: target });

      if (handler.oneOff) {
        EventHandler.off(element, event.type, selector, fn);
      }

      return fn.apply(target, [event]);
    }
  };
}

The Element.closest method is widely supported in modern browsers, aligning with Bootstrap's browser compatibility requirements.
https://caniuse.com/element-closest

If there are any potential side effects or edge cases I might have overlooked, I would greatly appreciate your feedback.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in js/src/dom/event-handler.js, especially bootstrapDelegationHandler, and compare its current traversal with the proposed Element.closest approach; review the delegated use in js/src/dropdown.js and the other listed components. Done means the handler is simplified as proposed, delegated events still target the correct element within document, and potential side effects or edge cases are addressed.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend
Issue type
Refactor
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.