Problem/Motivation
In js/init.js, when alerts are fetched and processed inside the initAlerts function, Drupal.attachBehaviors(); is called without a specific context element.
Because this call sits inside a forEach loop iterating over the active alerts, having multiple active alerts on the page causes Drupal.attachBehaviors() to fire globally on the entire document multiple times in rapid succession (once for each active alert).
We ran into this issue when it completely broke our custom tabs and accordions. Because the script re-runs across the entire page for every single active alert, it stacked multiple click listeners onto our buttons, causing them to glitch out. While we can update our own theme to guard against this, passing the context is a great best practice to ensure the module works smoothly across all types of projects and themes without causing accidental conflicts.
Steps to reproduce
- Have a site with custom JavaScript behaviors attached to DOM elements (like tabs or accordions).
- Create and activate more than one Sitewide Alert so that the
alerts.forEachloop runs multiple times. - Load a page displaying these alerts.
- Observe that
Drupal.attachBehaviors()is fired globally multiple times, causing unexpected behavior in other JavaScript components on the page.
Proposed resolution
Scope the behavior attachment specifically to the newly rendered alert element.
Change:
Drupal.attachBehaviors();
To:
Drupal.attachBehaviors(renderableAlertElement);
This ensures that behaviors are only attached to the markup injected by the module, preventing it from unnecessarily rescanning the entire page and interfering with other components.
Issue fork sitewide_alert-3585232
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3.1.x
changes, plain diff MR !104
- 3585232-global-drupal.attachbehaviors-in
compare
Comments
Comment #3
alimc29 commentedComment #4
chrissnyderThanks for the fix.
Comment #5
chrissnyderDo we also need to pass Drupal.settings as the second parameter?Edit: I just looked it up and attachBehaviors will default to drupalSettings if not passed
Comment #7
chrissnyderComment #9
chrissnyderComment #11
chrissnyderFixed in 3.1.2