javascripttwitter-bootstraphtml5-canvasbootstrap-5phaser-framework

Disabling Bootstrap event delegation for specific DOM elements


Environment

Problem Description

I'm developing a game using Phaser 3 within a Vue.js application that uses Bootstrap 5 for UI components. I've encountered a performance issue: whenever a user clicks to move a piece in the game, a Bootstrap click event is being triggered and processed, causing frame drops.

Using Chrome's performance profiler [screenshot], I can see that:

  1. Every click on the game canvas triggers a Bootstrap event handler
  2. These handlers take considerable time to process
  3. The game logic is handled by Phaser, not Bootstrap
  4. Removing bootstrap.min.js import increases frame rate

What I've Tried

I've attempted several approaches to prevent Bootstrap from handling events on the game container:

  1. Stop event in Vue.js. Result: disable both bootstrap and phaser event handling:
// In mounted() method
this.$refs.gameContainer.addEventListener('click', this.stopEvent, true);
this.$refs.gameContainer.addEventListener('mousedown', this.stopEvent, true);
// Same for mouseup, touchstart, touchend, touchmove

stopEvent: function(event) {
    event.stopPropagation();
    event.preventDefault();
}

  1. Selective event stop in Vue.js. Result: nothing changes:
stopEvent: function(event) {
    if (this.$refs.gameContainer && this.$refs.gameContainer.contains(event.target)) {
      const isBootstrapEvent = new Error().stack.includes('bootstrap');
      if (isBootstrapEvent) {
        event.stopPropagation();
        event.preventDefault();
      }
    }
}
  1. Stop event in Phaser.js. Result: nothing changes:
this.input.on("pointerdown", this.stopEvent, this);
this.input.on("pointerup", this.stopEvent, this);

stopEvent(pointer) {
    const event = pointer.event;
    event.stopPropagation();
    event.preventDefault();
}
  1. Using data-bs-no-jquery attribute. Result: nothing changes:
<div id="game-container" ref="gameContainer" data-bs-no-jquery="true"/>
  1. CSS pointer-events modifications. Result: disable both bootstrap and phaser event handling:
.bootstrap-element {
  pointer-events: none;
}

#game-container {
  pointer-events: auto;
}

Unfortunately, these solutions either:

Questions

  1. Is there an official way to tell Bootstrap to ignore events on specific DOM elements or containers?

  2. Is there a way to configure Bootstrap's event delegation system to exclude certain elements from event processing?

  3. Are there any known conflicts between Bootstrap's event handling and canvas-based libraries like Phaser, and any recommended solutions?

Any guidance would be greatly appreciated. Thank you!


Solution

  • I identified two key issues in my previous tests:

    1. Using stopPropagation() instead of stopImmediatePropagation() - the latter prevents all subsequent handlers from executing
    2. Adding event listeners after Bootstrap was already initialized

    Here's the working solution (must be placed before Bootstrap import):

    document.addEventListener('click', (event) => {
        if(event.target.nodeName === 'CANVAS') {
            event.stopImmediatePropagation();
        }
    }, true);
    
    import('bootstrap/dist/js/bootstrap.min.js');
    

    Although effective, this workaround has limitations:

    This approach blocks all click events on canvas elements, affecting both Phaser and Google Tag Manager. In my case, this wasn't problematic since I'm using mouseup/mousedown events in Phaser rather than click events.

    If you need click event functionality, you can follow @C3roe's suggestion to stop and then manually re-propagate the event to specific handlers.

    An official Bootstrap method to exclude specific DOM elements from event handling would be preferable.

    Performance comparison (Before/After)