Problem/Motivation

When bigpipe is enabled and I'm logged in (as admin), the context in Drupal.behavior functions is not the same as when logged out, so certain $('selectors', context) in behavior functions that work fine when logged out, do not work when logged in.

Steps to reproduce

A simple Drupal.Behavior function

(function (Drupal, once) {
  'use strict';

  Drupal.behaviors.bpBlockTest = {
    attach: function(context, settings) {
      once('bp-block-testin', '.my-block', context).forEach(el => {
        var addOn = document.createElement('span');
        addOn.innerHTML = 'addOn';
        el.after(addOn)';
      });
    }
  }

}(Drupal, once));

This works fine when big-pipe is not enabled or when you are logged out because the context that gets passed in these cases seems to be the HTML document.

But, when big-pipe is enabled and you are logged-in, the context passed is the element returned by bigpipe and no longer the HTML document, in this case <div class="my-block">....</div>

So my behavior code doesn't execute anymore because it is looking for $('.my-block') INSIDE the context of <div class="my-block">....</div> instead of inside <html>...</html>

So, without bigpipe or when logged out it works because:

$('.my-block', context = <html>...</html>).once('bp-block-testing').each(function () {
// gets exectuted
}

with big-pipe enabled and logged-in,

$('.my-block', context = <div class="my-block">....</div>).once('bp-block-testing').each(function () {
// does not get executed because jQuery is no longer looking for .my-block INSIDE the html context but INSIDE the .my-block context
}

essentially doing $('.my-block').find('.my-block') in this situation and finding nothing

Maybe this this is intended/normal but it breaks Drupal.Behavior execution in examples like above and it took me a long time to figure out why my JS was not working consistently through these different situations.

The solution is simple, remove the context, but since a lot of examples online do pass in the context to look for DOM elements, and all the examples on https://www.drupal.org/docs/drupal-apis/javascript-api/javascript-api-ov... this changes the conditions if a DOM element can be found in the context passed to a behavior function depending if big-pipe is enabled or not (and wether you are logged-in or not if it is enabled).

Comments

Percept created an issue. See original summary.

Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Ugh, formatting is hard

Percept’s picture

Title: Drupal.Behavior context difference when logged-in and logged-out breaks some $("selectors") » Drupal.Behavior context difference when logged-in and logged-out breaks some $("selectors", context)
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
Percept’s picture

Issue summary: View changes
rodrigoaguilera’s picture

Version: 9.0.x-dev » 10.1.x-dev
Issue summary: View changes

Interesting.
Someone on my team has been bitten by this.
Personally I think is bad developer experience having to remember selectors to avoid (like .block-xxxx) because they might be the context itself or adding additional logic to check if the context is the element you are trying to match.

Not sure of the way forward but adding the logic to check for the context matching the selector (with context.matches(selector)) would be ideal for me.

Updated the IS to use Drupal once as jQuery Once is removed in Drupal 10. Also use vanila JS.

wim leers’s picture

Title: Drupal.Behavior context difference when logged-in and logged-out breaks some $("selectors", context) » Simplify supporting AJAX/BigPipe in Drupal.behaviors: improve DX in case the selector to search is not in the given tree, but the root
Component: big_pipe.module » javascript
Category: Bug report » Feature request
Issue tags: +JavaScript, +DX (Developer Experience), +TX (Themer Experience)

But, when big-pipe is enabled and you are logged-in, the context passed is the element returned by bigpipe and no longer the HTML document, in this case

....

That is how the Drupal Behaviors API works, it's not related to BigPipe.

You can observe this in the AJAX API too — see Drupal.AjaxCommands.insert:

      // Attach all JavaScript behaviors to the new content, if it was
      // successfully added to the page, this if statement allows
      // `#ajax['wrapper']` to be optional.
      if ($newContent.parents('html').length) {
        // Attach behaviors to all element nodes.
        $newContent.each((index, element) => {
          if (element.nodeType === Node.ELEMENT_NODE) {
            Drupal.attachBehaviors(element, settings);
          }
        });
      }

👆 this only attaches behaviors to the newly inserted content, i.e. with the context not being the full document, but only the relevant DOM subtree.

So this is completely unrelated to BigPipe, but is just one of the several ways to surface this.

I do see how this can be confusing! Rescoping.

rodrigoaguilera’s picture

Issue summary: View changes

Fixed the code in the IS

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.